PL/SQL

简述

  通过ifloop等语句控制程序的执行流程,以及变量在语句间传递数据信息,将流程控制与sql的数据操作、查询结合,各取所长.

结构

  [declare]

    声明部分,可选

  Begin

    执行部分,必选

  [exception]

    异常处理,可选

  End;

  声明部分:用来定义变量,常量,游标等,且这些只能在当前块中使用,不能被其他块引用

  执行部分:完成主要的逻辑控制和运算可以包含多个PL/SQLsql语句;

  执行结束后,要么到异常处理,或者到end结束

 

  异常处理

  和Java代码中异常处理类似

  可以使用when...then分支语句来判断多种异常情况

 

  一个例子

  set SERVEROUTPUT ON;  --设置在服务器端输出结果

  DECLARE

      a int:=100;

      b int:=200; /*声明int型变量b并赋值*/

     c number;

  BEGIN

      c:=(a+b)/0;

      SYS.DBMS_OUTPUT.PUT_LINE(c); --输出变量c的值

  exception

      when zero_divide 

      then  SYS.DBMS_OUTPUT.PUT_LINE('除数不能为零');

  end;

 

合法字符集

  大小写字母 A-Z a-z

  数字 0-9

  非显示字符 空格,回车,制表符

  数学符号 +,-,*,/,>,<,=

  间隔符 (), {}, [], ?, !, ;, :, @

 

特殊数据类型(3)

  1.%type(与指定列名相同类型的值)

    格式:变量名 列名%type

    好处:a.可以不知道某列的数据类型;b.当列数据类型发生改变,也不会受到影响

 

  2.Record(是一种结构化数据类型)

    Type 记录类型名称 is record

    (

      成员变量名称 数据类型 [not null] [:=默认值],

      ...

      成员变量名称 数据类型 [not null] [:=默认值]

    )

    变量名 记录类型名称;(定义record类型变量)

    例:

    create table student

    (

        id int not null,

        name varchar2(50),

        birth date

    )

    DECLARE

       type emp_student is record

       (

          sid int,

          sname varchar2(50),

          sbirth date

       );

       stuInfo emp_student;

    BEGIN

       select id,name,birth

       into stuInfo

       from student

       where id=1;

       SYS.DBMS_OUTPUT.PUT_LINE(stuInfo.sname||'出生日期是'||stuInfo.sbirth);

    END;

 

  3.%rowtype(结合%typerecord的优点用来存储检索到的一行数据)

    格式:变量名 表名%rowtype

    例:

    DECLARE

        s student%rowtype;

    begin

        select *

        into s

        from student

        where id=1;

        SYS.DBMS_OUTPUT.PUT_LINE(s.name||'出生日期是'||s.birth);

    end;

 

定义变量和常量

  1.定义变量

    变量名 数据类型[(长度):=默认值];

    Name varchar2(50):=’超信’;

 

  2.定义常量

    变量名 constant 数据类型:=;

    Year_day constant int:=’365’;

 

流程控制语句

  1.If ... Then语句

    格式:

    if 表达式 then

      语句

    End if;

    表达式为true则执行语句否则不执行

 

  2.If ... Then ... Else

    格式:

    If 表达式 then

      语句1

    Else

      语句2

    End if;

 

  3.if ... Then elsif语句

    If 表达式 then

      语句

    Elsif 表达式 then

      语句

    Else

      语句

    End if;

 

  4.Case语句

    Case 选择器(一个变量)

      When 表达式(一般是个常量)  then 语句;

        ...

      [else 语句]

    End case;

 

循环语句(loop,while,for)

  1.Loop(Java中的do{...}while类似先执行一遍语句再判断)

    Loop 

      语句

      Exit when 表达式

    End loop;

 

  2.While(先判断,true则执行语句,否则不执行)

    While 表达式 loop

      语句

    End loop;

 

  3.For

    For 变量名 in [reverse] 下限值..上限值 loop

      语句

    End loop;

    没有reverse表示递增计数,有表示递减

    例:

    DECLARE

        i int:=3;

        su int:=0;

    begin

        For i in 9..10 loop

            su:=su+i;

        End loop;

          SYS.DBMS_OUTPUT.PUT_LINE(su);

    end;

    说明:计数从下限值开始,i初始是多少没有关系,此处i可以不必给初始值3

游标

  1.显示游标(通常用于查询结果集select语句,分四步:声明,打开,读取,关闭)

    a.声明游标

      Cursor 游标名[(参数列表)]

      [return 返回值类型]

      Is select语句;

 

      参数列表中参数格式

      参数名 [in] 数据类型 [ {:=|default} 默认值或表达式]

      In表示输入方向,可以省略

 

    b.打开游标

      Open 游标名[(参数列表)]

      此处参数列表和声明时代对应

 

    c.读取游标

      Fetch 游标名 into 变量

      此处变量可以说一个变量列表,也可以是一个record变量(推荐)

 

    d.关闭游标

      Close 游标名

 

    游标属性

      %found 判断是否有数据,有为true

      %notfound 与found相反

      %rowcount 返回函数

      %isopen 游标是否打开

    例:

    首先要创建student,插入数据

    DECLARE

        s student%rowtype;

        cursor cu

        is select * from student;

    begin

        open cu;

        fetch cu into s;

        while cu%found loop

            SYS.DBMS_OUTPUT.PUT_LINE(s.name);

            SYS.DBMS_OUTPUT.PUT_LINE(cu%rowcount);

            fetch cu into s;

            SYS.DBMS_OUTPUT.PUT_LINE(cu%rowcount);

        end loop;

        close cu;

    end;

    执行结果:

      daipeng

        1

        2

      caoxin

        2

        2

 

  2.隐式游标

    常用于修改,删除数据,特殊情况可以用于处理select查询结果.

    Oracle会默认创建一个隐式游标,名称是sql

    例:

    BEGIN

        update student

        set name='myq'

        where id=1;

        if sql%found then

            SYS.DBMS_OUTPUT.PUT_LINE('没有1号学生');

        else

            SYS.DBMS_OUTPUT.PUT_LINE('已修改');

        end if;

    end;

 

  3.For遍历游标

    For 变量名 in 游标名或查询语句 loop

      语句

    End loop;

    例:

    DECLARE

        cursor cu

        is select * from student;

    begin

        for s in cu loop

            SYS.DBMS_OUTPUT.PUT_LINE(s.name);

        end loop;

    end;

    还可以写成,效果相同:

    begin

        for s in (select * from student) loop

            SYS.DBMS_OUTPUT.PUT_LINE(s.name);

        end loop;

    end;

    特别说明:

    a.此处不要打开游标,否则报错

    b.此处的s自动设为record,并不要在声明部分声明,否则报错

 

异常处理

  1.预定义异常

    常用的

    ZERO_DIVIDE 除数为0

    ACCESS_INTO_NULL 给某个未初始化对象的属性赋值

    COLLECTION_IS_NULL 使用未初始化集合

    CURSOR_ALREADY_OPEN 多次打开同一个游标,第二次打开之前,没有关闭

    INVALID_CURSOR 非法游标操作,如为打开之前关闭游标

    INVALID_NUMBER 将字符串转换为数字失败

    LOGIN_DENIED 连接数据库的用户名或密码错误

    NO_DATA_FOUND select into语句没有返回值

    ROWTYPE_MISMATCH 类型不匹配

    SELF_IS_NULL 使用空对象调用对象方法

    SUBSCRIPT_BEYOND_COUNT 下标越界

    SUBSCRIPT_OUTSIDE_LIMIT 使用非法索引号引用表数据

    SYS_INVALID_ROWID rowid值无效

    TIMEOUT_ON_RESOURCE 等待数据超时

    TOO_MANY_ROWS 使用select into结果集超过一行

 

  2.自定义异常

    A.错误编号异常

      Declare

        异常名 exception;

        Pragma exception_init(异常名,错误号);--将错误号和异常绑定

      Begin

        ....

      Exception

        When 异常名 then

          语句

      End;

      说明:错误号就是执行语句时报的错ORA-XXXXX-XXXXX部分

        如:违反唯一约束会报ORA-00001,则错误号为-00001;

    B.业务逻辑异常

      Declare

        异常名 exception;

      Begin

        ....

        Raise 异常名;

        ...

      Exception

        When 异常名 then

          语句

      End;

 

posted @ 2015-10-17 17:43  爱上咖啡的唐  阅读(191)  评论(0编辑  收藏  举报