zoukankan      html  css  js  c++  java
  • oracle实战第三天事务处理与函数

    第三天

    内容介绍

    1. java程序如何操作oracle
    2. 如何在oracle中操作数据
    3. Oracle事务处理
    4. Sql函数的使用

    期望目标:

    1. 掌握oracle表对数据操作技巧。
    2. 掌握在java程序中操作oracle。
    3. 理解oracle事务概念。
    4. 掌握oracle各种sql函数。

    Java连接oracle

    前面我们一直在pl/sql中操作oracle,那么如何在java程序中操作数据库呢?

    下面我们举例说明:分页显示emp表的用户信息

    Testoracle.jsp

    <%@ page language="java" import="java.util.*,java.sql.*" pageEncoding="utf-8"%>

    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">

    <html>

      <head>  

        <title>oracle分页案例</title>

        <meta http-equiv="pragma" content="no-cache">

        <meta http-equiv="cache-control" content="no-cache">

      </head>

      <body>

        <h2>oracle分页案例</h2>

        <table>

        <tr>

            <td>雇员名</td>

            <td>薪水</td>

        </tr>

        <%

        //查询总页数

        int pageCount = 0;

        //总共有几条记录

        int rowCount = 0;

        //每页显示几条记录

        int pageSize = 3;

        //接收当前的页数

        String strPageNow = request.getParameter("pageNow");

        int pageNow = 1;

        if(strPageNow!=null)

        {

            pageNow = Integer.valueOf(strPageNow);

        }

       

        Connection conn = null;

           Statement stmt = null;

           try

           {

               //加载驱动

               Class.forName("oracle.jdbc.driver.OracleDriver");

               //得到连接

               conn = DriverManager.getConnection("jdbc:oracle:thin:@127.0.0.1:1521:orcl", "scott", "tiger");

               stmt = conn.createStatement();

              

               ResultSet rs= stmt.executeQuery("select count(*) from emp");

              

               while(rs.next())

               {

                  rowCount = rs.getInt(1);

                  if(rowCount%pageSize == 0)

                  {

                      pageCount = rowCount/pageSize;

                  }

                  else

                  {

                      pageCount = rowCount/pageSize + 1;

                  }

               }

              

               rs = stmt.executeQuery("select * from (select t.*,rownum rn from (select * from emp) t where rownum <=" + pageNow*pageSize + ") where rn >="+((pageNow-1)*pageSize + 1)+"");

     

               while (rs.next())

               {

                  out.print("<tr>");

                  out.print("<td>"+rs.getString(2)+"</td>");

                  out.print("<td>"+rs.getInt(6)+"</td>");

                  out.print("</tr>");

               }

              

               out.print("<tr>");

               for(int i =1 ; i<=pageCount; i++ )

               {

                  out.print("<a href='testoracle.jsp?pageNow="+i+"'>["+i+"]</a>");

               }

               out.print("</tr>");

           }

           catch (Exception e)

           {

               throw new RuntimeException(e);

           }

           finally

           {

               try

               {

                  if (stmt != null)

                  {

                      stmt.close();

                  }

                  if (conn != null)

                  {

                      conn.close();

                  }

               }

               catch (Exception ex)

               {

                  throw new RuntimeException(ex);

               }

           }

        %>

        </table>

      </body>

    </html>

    在oracle中操作数据

    使用特定格式插入日期值--使用to_date()函数

    请思考:如何插入列带有日期的表,并按照年-月-日的格式插入?

    insert into emp
    values
    (7950,'ZHANGSAN','MANAGER','7782',
    to_date('1988-11-11','yyyy-mm-dd'),
    1200.00,50.00,10);

    insert into emp
    values
    (7951,'ZHANGSAN','MANAGER','7782',
    to_date('1988/11/11','yyyy/mm/dd'),
    1200.00,50.00,10);

    使用子查询插入数据

    当使用values子句时,一次只能插入一行数据,当使用子查询插入数据时,一条insert语句可以插入大量的数据,当处理行迁移或者装载外部表的数据到数据库时,可以使用子查询来插入数据。

    create table myemp
    (
        myId number(4),
        myName varchar2(50),
        myDept number(5)
    );

    insert into myemp(myId,myname,mydept)
    select empno,ename,deptno from emp
    where deptno = 10;

    select * from myemp;

    使用子查询更新数据

    使用update语句更新数据时,既可以使用表达式或者数值直接修改数据,也可以使用子查询修改数据。

    如:希望员工scott的岗位、工资、补助与smith员工一样

    update emp set (job,sal,comm)
    = (select job,sal,comm from emp where ename='SMITH')
    where ename = 'SCOTT';

    Oracle中事务处理

    事务用于保证数据的一致性,它由一组相关的dml语句组成,该组的dml语句要么全部成功,要么全部失败。

    如:网上转帐就是典型的要用事务处理,用以保证数据的一致性。

    事务和锁

    当执行事务操作时(dml语句),oracle会在被作用的表上加锁,防止其它用户改表的结构,这里对我们用户来讲是非常重要的。

    提交事务

    当执行commit语句可以提交事务,当执行了commit语句后,会确认事务的变化、结束事务、删除保存点、释放锁,当使用commit语句结束事务后,其它会话将可以查看到事务变化后的新数据。

    回退事务

    在介绍回退事务前,我们先介绍一下保存点(savepoint)的概念和作用,保存点是事务中的一点,用于取消部分事务,当结束事务时,会自动的删除该事务所定义的所有保存点。当执行rollback时,通过指定保存点可以回退指定的点。

    savepoint a1;

    delete from emp where empno = 7900;

    savepoint a2;

    delete from emp where empno = 7788;

    rollback to a2;

    rollback to a1;

    事务的几个重要操作

    a.设置保存点

    svepoint a;

    b.取消部分事务

    Rollback to a;

    c.取消全部事务

    Rollback;

    在java程序中如何使用事务

    在java操作数据库时,为了保证数据的一致性,比如转帐操作

    1)  在一个帐户减掉10元

    2)  在另一个帐户加上10元

    我们看看如何使用事务?

    package com.anllin.jdbc.oracle;

     

    import java.sql.*;

     

    public class TestTransation

    {

        public static void main(String[] args)

        {

           Connection conn = null;

           Statement stmt = null;

     

           try

           {

               Class.forName("oracle.jdbc.driver.OracleDriver");

               conn = DriverManager.getConnection(

                      "jdbc:oracle:thin:@127.0.0.1:1521:orcl", "scott", "tiger");

               //加入事务处理

               conn.setAutoCommit(false);

     

               stmt = conn.createStatement();

               stmt.executeUpdate("update emp set sal=sal-100 where ename='SCOTT'");

              

               //制造异常

               int i = 7/0;

              

               stmt.executeUpdate("update emp set sal=sal+100 where ename='SMITH'");

               //提交事务

               conn.commit();

           }

           catch (Exception e)

           {

               try

               {

                  //回滚事务

                  conn.rollback();

               }

               catch (SQLException e1)

               {

                  throw new RuntimeException(e1);

               }

               throw new RuntimeException(e);

           }

           finally

           {

               if(stmt != null)

               {

                  try

                  {

                      stmt.close();

                  }

                  catch (SQLException e)

                  {

                      throw new RuntimeException(e);

                  }

               }

               if(conn != null)

               {

                  try

                  {

                      conn.close();

                  }

                  catch (SQLException e)

                  {

                      throw new RuntimeException(e);

                  }

               }

           }

        }

    }

    只读事务

    只读事务是指只允许执行查询的操作,而不允许执行其它dml操作的事务,使用只读事务可以确保用户只能取得某时间点的数据,

    假定机票代售点每天18点开始统计今天的销售情况,这时可以使用只读事务,在设置了只读事务后,尽管其它会话可能会提交新的事务,但是只读事务将不会取得最新数据的变化,从而可以保证取得特定时间点的数据信息。

    设置只读事务

    set transaction read only;

    用system用户登录,然后执行以下操作:

    set transaction read only;

    再另外起一个客户端,用scott用户登录,执行以下操作:

    insert into emp(empno,ename,job,mgr,hiredate,sal,comm,deptno)
    values(8000,'LISI','CLERK',7902,to_date('1983-05-16','yyyy-mm-dd'),1200.00,50.00,10);

    select * from emp;--可以看到新增的数据

    此时,再用system用户操作

    select * from scott.emp; --将看不到新增的数据

    Sql函数的使用

    字符函数

    介绍:

    字符函数是oralce中最常用的函数,我们来看看有哪些字符函数:

    Lower(char): 将字符串转化为小写的格式

    Upper(char): 将字符串转化为大写的格式

    Length(char): 返回字符串的长度

    Substr(char,m,n): 取字符串的子串,m表示截取起始位置,n表示截取的长度

    将所有员工的名字按小写的方式显示

    select lower(ename),sal,job from emp;

    将所有员工的名字按大写的方式显示

    select upper(ename),sal,job from emp;

    显示正好为5个字符的员工的姓名

    select * from emp where length(ename) = 5;

    显示所有员工姓名的前三个字符。

    select substr(ename,1,3) from emp;

    以首字母大写的方式显示所有员工的姓名

    select upper(substr(ename,1,1))
    ||
    lower(substr(ename,2,length(ename)-1))
    from emp;

    以首字母小写的方式显示所有员工的姓名。

    select lower(substr(ename,1,1))
    ||
    upper(substr(ename,2,length(ename)-1))
    from emp;

    Replace(char1,search_string,replace_string):将字符中某段字符串替换成所需的字符串

    Instr(char1,char2,[n[,m]])取子串在字符串的位置

    显示所有员工的姓名,用a替换所有”A”

    select replace(ename,'A','a') from emp;

    数学函数

    介绍:

    数学函数的输入参数和返回值的数据类型都是数字类型的,数学函数包括

    Abs(n) 返回数字n的绝对值。

    Cos(n) 返回数字的余弦值。

    Cosh(n) 返回数字的双曲余弦值

    exp(n) 返回数字e的n次幂

    power(m,n) 返回m的n次幂

    ln(n)  返回e为底的n的对数

    log(m,n)  返回m为底的n的对数

    sin(n) 返回数字的正弦值

    sinh(n) 返回数字的双曲正弦值

    sqrt(n) 返回数字的平方根

    tan(n) 返回数字的正切值

    tanh(n) 返回数字的双曲正切值

    acos(n) 返回数字的反余弦值

    asin(n) 返回数字的反正弦值

    atan(n) 返回数字的反正切值

    我们最常用的有:

    Round(n,[m])该函数用于执行四舍五入。如果省掉m,则四舍五入到整数;如果m是正数,则四舍五入到小数点的m位后;如果m是负数,则四舍五入到小数点的m位前。

    Trunk(n,[m])该函数用于截取数字。如果省掉m,就截去小数部分,如果m是正数,就截取到小数点的m位后,如果m是负数,则截取到小数点的前m位。

    Mod(m,n)取模

    Floor(n)返回小于或等于n的最大整数

    Ceil(n)返回大于或等于n的最小整数

    对数字的处理,在财务系统或银行系统中用的最多,不同的处理方法,对财务报表有不同的结果。

    案例:

    显示在一个月为30天的情况所有员工的薪金,忽略余数。

    select trunc(sal/30),ename from emp;

    output:

    TRUNC(SAL/30) ENAME

    ------------- ----------

               40 LISI

               43 zhangsan

               51 wangwu

               49 zhaoliu

               30 SMITH

               53 ALLEN

               41 WARD

               99 JONES

               41 MARTIN

               95 BLAKE

               81 CLARK

               20 SCOTT

              166 KING

               50 TURNER

               36 ADAMS

               31 JAMES

              100 FORD

               43 MILLER

    示例:

    insert into emp(empno,ename,job,mgr,hiredate,sal,comm,deptno)
    values(8001,'zhangsan','CLERK',7902,to_date('1983-06-18','yyyy-mm-dd'),1300.34,50.52,10);
    insert into emp(empno,ename,job,mgr,hiredate,sal,comm,deptno)
    values(8002,'wangwu','CLERK',7902,to_date('1983-09-22','yyyy-mm-dd'),1530.69,50.14,10);
    insert into emp(empno,ename,job,mgr,hiredate,sal,comm,deptno)
    values(8003,'zhaoliu','CLERK',7902,to_date('1983-10-20','yyyy-mm-dd'),1480.52,50.73,10);

    select round(sal),sal from emp

    Output:

    ROUND(SAL)       SAL

    ---------- ---------

          1200   1200.00

          1300   1300.34

          1531   1530.69

          1481   1480.52

    select round(sal,1),sal from emp;

    output:

    ROUND(SAL,1)       SAL

    ------------ ---------

            1200   1200.00

          1300.3   1300.34

          1530.7   1530.69

          1480.5   1480.52

    select trunc(sal),sal from emp;

    output:

    TRUNC(SAL)       SAL

    ---------- ---------

          1200   1200.00

          1300   1300.34

          1530   1530.69

          1480   1480.52

    select trunc(sal,1),sal from emp;

    output:

    TRUNC(SAL,1)       SAL

    ------------ ---------

            1200   1200.00

          1300.3   1300.34

          1530.6   1530.69

          1480.5   1480.52

    select floor(sal),sal from emp;

    output:

    FLOOR(SAL)       SAL

    ---------- ---------

          1200   1200.00

          1300   1300.34

          1530   1530.69

          1480   1480.52

    select ceil(sal),sal from emp;

    output:

    CEIL(SAL)       SAL

    ---------- ---------

          1200   1200.00

          1301   1300.34

          1531   1530.69

          1481   1480.52

    select mod(10,3) from dual;

    output:

    MOD(10,3)

    ----------

             1

    日期函数

    介绍:

    日期函数用于处理date类型的数据。

    默认情况下日期格式是dd-mon-yy 即12-7月-78

    1)sysdate该函数返回系统时间

    2)add_months(d,n)给指定日期增加n 个月份

    3)last_day(d)返回指定日期所在月分的最后一天

    查找已经入职8个月多的员工

    select * from emp where sysdate > add_months(hiredate,8);

    显示满10年服务年限的员工的姓名和受雇日期。

    select * from emp where sysdate >= add_months(hiredate,12*10);

    对于每个员工,显示其加入公司的天数。

    select trunc(sysdate-hiredate) days,ename from emp;

    找出各月倒数第3天受雇的所有员工。

    select hiredate,last_day(hiredate),ename from emp
    where last_day(hiredate)-2 = hiredate;

    转换函数

    转换函数用于将数据类型从一种转为另外一种,在某些情况下,oracle server 允许值的数据类型和实际的不一样,这时oracle server会隐含的转化数据。

    比如:

    create table t1(id int);
    insert into t1 values('10');--这里oracle会自动将'10'->10

    create table t2(id varchar2(10));
    insert into t2 values(1);-- 这里oracle会自动将1->'1'

    我们要说的尽管oracle可以进行隐含的数据类型的转换,但是它并不适应所有的情况,为了提高程序的可靠性,我们应该使用转换函数。

    To_char()

    你可以使用

    select ename,hiredate,sal from emp where deptno=10;

    显示信息,可是,在某些情况下,这个并不能满足你的需求.

    格式

    描述

    示例

    yy

    两位数字的年份

    2004à04

    yyyy

    四位数字的年份

    2004年à2004

    mm

    两位数字的月份

    8月à08

    dd

    2位数字的天

    30号à30

    hh24

    小时用24小时制

    8点à20

    hh12

    小时用12小时制

    8点à08

    mi

    分钟

    15

    ss

    50

    格式

    描述

    9

    显示数字,并忽略前面0

    0

    显示数字,如位数不足,则用0补齐

    .

    在指定位置显示小数点

    ,

    在指定位置显示逗号

    $

    在数字前加美元符

    L

    在数字前加本地货币符号

    C

    在数字前加国际货币符号

    G

    在指定位置显示组分隔符、

    D

    在指定位置显示小数点符号.

    如:日期是否可以显示时、分、秒

    insert into emp
    values(8004,'Test','MANAGER',7782,sysdate,1360.52,100,20);

    select ename,to_char(hiredate,'yyyy-mm-dd hh24:mi:ss')
    from emp;

    Output:

    Test       2012-02-09 20:09:45

    薪水是否可以显示指定的货币符号。

    select ename,to_char(hiredate,'yyyy-mm-dd hh24:mi:ss'),
    to_char(sal,'L99999.99')
    from emp;
    output:

    ENAME      TO_CHAR(HIREDATE,'YYYY-MM-DDHH TO_CHAR(SAL,'L99999.99')

    ---------- ------------------------------ ------------------------

    Test       2012-02-09 20:09:45                     ¥1360.52

    LISI       1983-05-16 00:00:00                     ¥1200.00


    select ename,to_char(hiredate,'yyyy-mm-dd hh24:mi:ss'),
    to_char(sal,'L99,999.99')
    from emp;

    output:

    ENAME      TO_CHAR(HIREDATE,'YYYY-MM-DDHH TO_CHAR(SAL,'L99,999.99')

    ---------- ------------------------------ -------------------------

    Test       2012-02-09 20:09:45                     ¥1,360.52

    LISI       1983-05-16 00:00:00                     ¥1,200.00

    显示1980年入职的所有员工

    select * from emp where to_char(hiredate,'yyyy') = 1980;

    output:

    EMPNO ENAME      JOB         MGR HIREDATE          SAL      COMM DEPTNO

    ----- ---------- --------- ----- ----------- --------- --------- ------

     7369 SMITH      CLERK      7902 1980-12-17     900.00               20

    显示所有12月份入职的员工

    select * from emp where to_char(hiredate,'mm') = 12;

    output:

    EMPNO ENAME      JOB         MGR HIREDATE          SAL      COMM DEPTNO

    ----- ---------- --------- ----- ----------- --------- --------- ------

     7369 SMITH      CLERK      7902 1980-12-17     900.00               20

     7900 JAMES      CLERK      7698 1981-12-03     950.00               30

     7902 FORD       ANALYST    7566 1981-12-03    3000.00               20

    To_date()

    用于将字符串转换成date类型的数据。

    能否按照中国人习惯的方式年-月-日添加日期。

    insert into emp
    values(8005,'ChenWen','ANALYST',7566,to_date('1986-9-22','yyyy-mm-dd'),1850.52,100,20);

    系统函数

    1)terminal: 当前会话客户所对应的终端的标识符。

    2)language: 语言。

    3)db_name: 当前数据库名称。

    4)nls_date_format: 当前会话客户所对应的日期格式。

    5) session_user: 当前会话客户所对应的数据库用户名。

    6)current_schema: 当前会话客户所对应的默认方案名。

    7)host: 返回数据库所在主机的名称。

    通过该函数,可以查询一些重要信息,

    比如你正在使用哪个数据库?

    select sys_context('userenv','db_name') as dbname from dual;

    output:

    DBNAME

    --------------------------------------------------------------------------------

    Orcl

    select
    sys_context('userenv','terminal') as dbterminal,
    sys_context('userenv','language') as dblanguage,
    sys_context('userenv','session_user') as sessionuser,
    sys_context('userenv','current_schema') as currentschema,
    sys_context('userenv','host') as dbhost,
    sys_context('userenv','nls_date_format') as dateformat,
    sys_context('userenv','db_name') as dbname
    from dual;

    output:

    DBTERMINAL                                                             DBLANGUAGE                                                                       SESSIONUSER                                                                      CURRENTSCHEMA                                                                    DBHOST                                                                           DATEFORMAT                                                                       DBNAME

    --------------------------------------------------------------

    2011-20030430JR                                                                  SIMPLIFIED-CHINESE_CHINA.AL32UTF8                                                SCOTT                                                                           SCOTT                                                                            WORKGROUP\2011-20030430JR                                                        DD-MON-RR                                                                        orcl

  • 相关阅读:
    JAVA代码覆盖率工具JaCoCo-原理篇
    (转载)比较web ui 框架
    sql拼接
    解决com.mysql.jdbc.PacketTooBigException: Packet for query is too large问题
    字符串中重复出现字符串个数
    Unable to load annotation processor factory
    三目运算符
    WSGI剖析
    深入剖析cpp对象模型
    Cpp下匿名对象探究
  • 原文地址:https://www.cnblogs.com/zfc2201/p/2344529.html
Copyright © 2011-2022 走看看