zoukankan      html  css  js  c++  java
  • Oracle学习笔记5 PL/SQL编程

    一、PL/SQL简介

    1、PL/SQL块结构

    [DECLARE]

    --声明部分,可选

    BEGIN

    --执行部分,必须

    [EXCEPTION]

    --一场处理部分,可选

    END

    (1)声明部分由关键字DECLARE开始,到BEGIN结束。在这部分可以声明PL/SQL程序块中所用到的变量、常量和游标。需要注意的是:在某个PL/SQL块中声明的内容只能在当前块中使用,而在其他PL/SQL块中是无法引用的。

    (2)执行部分以BEGIN开始,它的结束方式通常有两种。如果PL/SQL块中的代码在运行时出现异常,则执行完异常处理部分的代码就结束;如果没有使用异常处理或PL/SQL块未出现异常,则以关键字END结束。

    (3)异常处理部分以关键字EXCEPTION开始,在该关键字所包含的代码执行完毕后,整个PL/SQL块就结束了。对于可能出现的多种异常情况,用户可以使用WHEN  THEN语句来实现多分支判断,然后再每个分支下通过编写代码来处理相应的异常;

    (4)对于PL/SQL块中的语句,需要指出的是:每一条语句必须以分号结束,每条SQL语句可以写成多行的形式,同样必须使用分号来结束。另外,一行中也可以有多条SQL语句,但是他们之间必须以分号隔开。

    2、代码注释和标识符

    (1)单行注释

    单行注释由两个连接字符--开始,后面紧跟这注释内容;

    (2)多行注释

    多行注释由/*开头,以*/结尾,这种多行注释的方法再大多数的编程语言中是相同的。

    二、数据类型、变量和常量

    1、基本数据类型

    (1)  数值类型

    数值类型主要包括:NUMBER、PLS_INTEGER和BINARY_INTEGER三种类型;

    (2)字符类型

    字符类型主要包括VARCHAR2、CHAR、LONG、NCHAR和NVARCHAR2等;这些类型的变量用来存储字符串或者字符数据。

    (3)日期类型

    日期类型只有一种类型,用来存储日期和时间信息,DATE类型的存储空间是7个字节,分别使用一个字节存储世纪、年、月、天、小时、分钟和秒。

    (4)布尔类型

    布尔类型也只有一种——即BOOLEAN,主要用于程序的流程控制和业务逻辑判断,其变量值可以是TRUE、FALSH或NULL中的一种。

    2、特殊数据类型

    (1) %TYPE类型

    使用%TYPE关键字可以声明一个与指定列明相同的数据类型,它通常紧跟再指定列明的后面

    示例1:声明一个与表EMP中job列相同的数据类型。

    SQL> declare 

               var_job emp.job%type;

    示例2:使用%TYPE类型的变量输出EMP表中编号为7369的员工名称和职务信息。

    set serveroutput on                                                            --在服务端输出
    declare
    var_ename emp.ename%type;                                          --声明与ename列类型相同的变量
    var_job emp.job%type;                                                      --声明与job列类型相同的变量
    begin
    select ename,job
    into var_ename,var_job
    from emp
    where empno=7369;                                                         --检索数据,并保存在变量中
    dbms_output.put_line(var_ename||'的职务是'||var_job);   --输出变量的值
    end;
    /

    (2)RECORD类型

    RECORD类型也称作记录类型,使用该类型的变量可以存储由多个列值组成的一行数据。在声明记录类型前,首先需要定义记录类型,然后才可以声明记录类型的变量。记录类型是一种结构化的数据类型,它使用TYPE语句进行定义,在记录类型的定义结构中包含成员变量及其数据类型,其语法格式如下:

    type record_type is record 

         var_member1 data_type [not null] [:=default_value,

         ...

         var_membern data_type [not null] [:=default_value])

    record_type :表示要定义的记录类型名称;

    var_member1:表示该记录类型的成员变量名称;

    data_type:表示成员变量的数据类型。

    示例1:声明一个记录类型emp_type,然后使用该类型的变量存储emp表中的一条记录信息,并输出这条记录信息;

    set serveroutput on                                            --输出到服务端
    declare
    type emp_type is record                                    --声明record类型emp_type
    (
    var_ename varchar2(20),                                   --定义字段
    var_job varchar2(20),
    var_sal number
    );
    empinfo emp_type;                                             --定义变量
    begin
    select ename,job,sal
    into empinfo
    from emp
    where empno=7369;                                           --检索数据

    dbms_output.put_line('雇员'||empinfo.var_ename||'的职务是'||empinfo.var_job||'、工资是'||empinfo.var_sal);                                          --输出雇员信息
    end;
    /

    (3)%ROWTYPE类型

    %ROWTYPE类型的变量结合了%TYPE类型和记录类型变量的优点,它可以根据数据表中行的结构定义一种特殊的数据类型,用来存储从数据表中检索出的一行数据,他的语法形式如下:

    rowVar_name table_name%ROWTYPE;

    rowVar_name:表示可以存储一行数据的变量名;

    table_name:指定的表名;

    示例1:声明一个%ROWTYPE类型的变量rowVar_emp,然后使用该变量存储emp表中的一行数据;

    set serveroutput on                                                 --输出到服务端
    declare
    rowVar_emp emp%rowtype;                                   --定义能够存储emp表中一行数据的变量rowVar_emp
    begin
    select *
    into rowVar_emp
    from emp
    where empno=7369;--检索数据

    dbms_output.put_line('雇员'||rowVar_emp.ename||'的编号是'||rowVar_emp.empno||',职务是'||rowVar_emp.job);   /*输出雇员信息*/

    end;
    /

    3、定义变量和常量

    (1) 定义变量

    <变量名> <数据类型> [(长度) :=<初始值>] ;

    (2) 定义常量

    <常量名> constant <数据类型> :=<常量名> ;

    三、流程控制语句

    1、选择语句

    (1) IF...THEN语句

    IF...THEN语句是选择语句中最简单的一种形式,它只做一种情况和条件的判断,其语法如下

    IF<condition_expression> THEN

    plsql_sentence

    END IF;

    condition_expression:表示一个表达式,当其值为TRUE时,程序会执行IF下面的PL/SQL语句(即plsql_sentence语句);如果其值为FLASE,则程序会跳过IF下面的语句而直接执行END IF 后面的语句。

    plsql_sentence:当condition_expression表达式的值为TRUE时,要执行的PL/SQL语句。

    示例1:定义两个字符串变量,然后赋值,接着使用IF...THEN语句比较两个字符串变量的长度,并输出比较结果。

    set serveroutput on            --输出到服务端
    declare
    var_name1 varchar2(50);  --定义变量1
    var_name2 varchar2(50);  --定义变量2
    begin
    var_name1:='East';             --为变量1赋值
    var_name2:='xiaoke';          --为变量2赋值
    if length(var_name1) < length(var_name2) then  --比较两个字符串的长度大小
    dbms_output.put_line('字符串“'||var_name1||'”的长度比字符串“'||var_name2||'”的长度小');
    end if;
    end;
    /

    (2) IF...THEN...ELSE

    IF...THEN...ELSE语句是最常用到的一种选择语句,它可以实现判断两种情况,只要IF后面的变大时为FALSE,程序就会执行ELSE语句下面的PL/SQL语句。其语法格式如下:

    IF<condition_expression> THEN

    plsql_sentence1;

    ELSE

    plsql_sentence2

    END IF;

    condition_expression:表示一个表达式,当其值为TRUE时,程序会执行IF下面的PL/SQL语句(即plsql_sentence1语句);否则,程序将执行ELSE下面的OL/SQL语句,即plsql_sentence2语句。

    plsql_sentence1:IF语句的表达式值为TRUE时,要执行的PL/SQL语句;

    plsql_sentence2:IF语句的表达式值为FLASE时,要执行的PL/SQL语句。

    (3) IF...THEN...ELSIF语句

    IF...THEN...ELSIF语句实现了多分支判断选择,它使程序的判断选择条件更加丰富,更加多样化。该语句中的哪个判断分支的表达式为TRUE,那么程序就会执行其下面对应的PL/SQL语句,其语法格式如下:

    IF<condition_expression1> THEN

    plsql_sentence_1;

    ELSIF <condition_expression2> THEN

    plsql_sencence_2;

    ...

    ELSE

    plsql_sentence_n;

    END IF;

    condition_expression_1:第一个表达式,若其值为FLASE,则程序继续判断condition_expression_2;

    condition_expression_2:第二个表达式,若其值为FLASE,则程序继续判断下面的ELSIF语句后面的表达式,若再没有ELSIF语句,则程序将执行ELSE语句下面的PL/SQL语句;

    plsql_sentence_1:第一个条件表达式的值为TRUE时,要执行的PL/SQL语句;

    plsql_sentence_2:第二个条件表达式的值为TRUE时,要执行的PL/SQL语句;

    plsql_sentence_n:当其上面所有的条件表达式的值都为FLASE时,要执行的PL/SQL语句。

    示例1:指定一个月数值,然后使用IF...THEN...ELSIF语句判断它所属的季节,并输出季节信息。

    set serveroutput on                                 ----输出到服务端
    declare
    month int:=10;                                         --定义整形变量并赋值
    begin
    if month >= 0 and month <= 3 then          --判断春季
    dbms_output.put_line('这是春季');
    elsif month >= 4 and month <= 6 then     --判断夏季
    dbms_output.put_line('这是夏季');
    elsif month >= 7 and month <= 9 then     --判断秋季
    dbms_output.put_line('这是秋季');
    elsif month >= 10 and month <= 12 then  --判断冬季
    dbms_output.put_line('这是冬季');
    else
    dbms_output.put_line('对不起,月份不合法!');
    end if;
    end;
    /

    (4) CASE语句

    CASE语句的执行方式与IF...THEN...ELSIF语句十分相似。在CASE关键字的后面有一个选择器,它通常是一个变量,程序就从这个选择器开始执行,接下来是WHEN子句,并且在WHEN关键字的后面是一个表达式,程序将根据选择器的值去匹配每个WHEN子句中的表达式的值,从而实现执行不同的PLSQL语句的功能,其语法格式如下:

    CASE <selector>

         WHEN <expression_1> THEN plsql_sentence_1;

         WHEN <expression_1> THEN plsql_sentence_2;

    ...

         WHEN <expression_n> THEN plsql_sentence_n;

    END CASE;

    selector :一个变量,用来存储要检测的值,通常称为选择器。该选择器的值需要与WHEN子句中的表达式的值进行匹配。

    expression_1:第一个WHEN子句中的表达式,它通常是一个常量,当选择器的值等于该表达式的值时,程序将执行plsql_sentence_1语句;

    expression_2:第二个WHEN子句中的表达式,它通常也是一个常量,当选择器的值等于该表达式的值时,程序将执行plsql_sentence_1语句;

    expression_n:第n个WHEN子句中的表达式,它通常也是一个常量,当选择器的值等于该表达式的值时,程序将执行plsql_sentence_n语句;

    plsql_sentence:一个PL/SQL语句,当没有与选择器匹配的WHEN常量时,程序执行该PL/SQL语句,其所在的EKSE语句是一个可选项;

    示例1:指定一个季度数值,然后使用CASE语句判断它所包含的月份信息并输出。

    set serveroutput on                                   --输出到服务端
    declare
    season int:=3;                                            --定义整形变量并赋值
    aboutInfo varchar2(50);
    begin
    case season 
    when 1 then
    aboutInfo := season||'季度包括1,2,3月份';
    when 2 then
    aboutInfo := season||'季度包括4,5,6月份';
    when 3 then
    aboutInfo := season||'季度包括7,8,9月份';
    when 4 then
    aboutInfo := season||'季度包括10,11,12月份';
    else
    aboutInfo := season||'季节不合法';
    end case;
    dbms_output.put_line(aboutinfo);             ---输出结果
    end;
    /

    2、循环语句

    (1) LOOP语句

    LOOP语句会先执行一次循环体,然后判断EXIT WHEN关键字后面的条件表达式的值是TRUE还是FLASE,如果是TRUE,则程序会推出循环体,否则程序将再次执行循环体,这样就使得程序至少能够执行一次循环体,其语法格式如下:

    LOOP

        plsql_sentence;

        EXIT WHEN end_condition_exp

    END LOOP;

    plsql_sentence:循环体中的PL/SQL语句,可能是一条语句,也可能是多条,这是循环体的核心部分,这些PL/SQL语句至少会被执行一遍。

    end_condition_exp:循环结束条件表达式,当该表达式的值为TRUE时,程序会退出循环体,否则程序将再次执行循环体。

    (2) WHILE语句

    WHILE语句根据它的条件表达式的值执行零次或多次循环体,在每次执行循环体之前,首先要判断条件表达式的值是否为TRUE,若为TRUE,则程序执行循环体;否则推出WHILE循环,然后继续执行WHILE语句后面的其他代码,其语法格式如下:

    WHILE condition_expression LOOP

        plsql_sentence;

    END LOOP;

    condition_expression:表示一个条件表达式,当其值为TRUE时,程序执行循环体,否则程序退出循环体,程序每次执行循环体之前,都要首先判断该表达式的值是否为TRUE。

    plsql_sentence:循环体内的PLSQL语句。

    示例1:使用WHILE语句球的前100个自然数的和,并输出结果。

    set serveroutput on
    declare
    sum_i int:= 0;                                   --定义整数变量,存储整数和
    i int:= 0;                                            --定义整数变量,存储自然数
    begin
    while i<=99 loop
    i:=i+1;--得出自然数
    sum_i:= sum_i+i;--计算前n个自然数的和
    end loop;
    dbms_output.put_line('前100个自然数的和是:'||sum_i);--计算前100个自然数的和
    end;
    /

    (3) FOR语句

    FOR语句时一个可预置循环次数的循环控制语句,它有一个循环计数器,通常是一个整型变量,通过这个循环计数器来控制循环执行的次数。该计数器可以从小到大进行记录,也可以相反,从大到小进行记录。另外,该计数器值的合法性由上限值和下限值控制,托计数器值在上限值和下限值的范围内,则程序执行循环,否则,种植循环,其语法格式如下:

    FOR variable_counter_name in [REVERSE] lower_limit...upper_limit LOOP

    plsql_sentence;

    END LOOP;

    variable_counter_name:表示一个变量,通常为整数类型,用来作为计数器。默认情况下计数器的值会循环递增,当在循环中使用REVERSE关键字时,计数器的值会随循环递减。

    lower_limit:计数器的下限值,当计数器的值小于下限值时,程序终止FOR循环;

    upper_limit:计数器的上限值,当计数器的值大于上限值时,程序终止FOE循环;

    plsql_sentence:表示PL/SQL语句,作为FOE语句的循环体。

    示例1:使用FOR语句求得前100个自然数中偶数之和,并输出结果;

    set serveroutput on
    declare
    sum_i int:= 0;                               --定义整数变量,存储整数和
    begin
    for i in reverse 1..100 loop           --遍历前100个自然数
    if mod(i,2)=0 then                        --判断是否为偶数
    sum_i:=sum_i+i;                          --计算偶数和
    end if;
    end loop;
    dbms_output.put_line('前100个自然数中偶数之和是:'||sum_i);
    end;
    /

    四、 PL/SQL游标

    1、显式游标

    显示游标是由用户声明和操作的一种游标,通常用于操作查询结果集(即由SELECT语句返回的查询结果),使用它处理数据的步骤包括声明游标、打开游标、读取游标和关闭游标4个步骤。

    (1) 声明游标

    声明游标主要包括游标名称和为游标提供结果集的SELECT语句。因此声明游标时,必须指定游标名称和游标所使用的人SELECT语句,声明游标格式如下:

    CURSOR cur_name[input_parameter1 [,input_parameter2]...]

    [RETURN ret_type]

    IS select_sentence;

    cur_name:表示所声明的游标名称;

    ret_type:表示执行游标操作后的返回值类型,这是一个可选项;

    select_srntence:游标所使用的SELECT语句,它为游标的反复读取提供了结果集;

    input_parameter1:作为游标的输入参数,可以有多个,这是一个可选项。它指定用户在打开游标后向游标中传递的值,该参数的定义和初始化格式如下:

    para_name [IN] DATATYPE [{:= | DEFAULT}para_value]

    其中,para_name表示参数名称,其后面的关键字IN表示输入方向,可以省略;DATATYPE表示参数的数据类型,但数据类型不可以指定长度;para_value表示该参数的初始值或默认值,它也可以时一个表达式;para_name参数的初始值既可以以常规的方式赋值(:=),也可以使用关键字DEFAUKT初始化默认值。

    示例:声明一个游标,用来读取emp表中职务为销售员的雇员信息:

    declare
    /*声明游标,检索雇员信息*/
    cursor cur_emp (var_job in varchar2:='SALESMAN')
    is select empno,ename,sal
    from emp
    where job=var_job;

    (2)打开游标

    在声明游标完毕之后,必须打开才能使用,打开游标的语法格式如下:

    OPEN cur_name[(para_value1[,para_value2]...)]

    cur_name:要打开的游标名称;

    oara_value1:指定输入参数的值,根据声明游标时的实际情况,可以时多个或一个,这是一个可选项。如果在声明游标时定义了输入参数,并初始化其值,而在此处省略“输入参数”的值,则表示游标将使用“输入参数”的初始值;若在此处指定“输入参数”的值,则表示游标将使用这个指定的参数值。

    打开游标就是执行定义的SELECT语句。执行完毕,查询结果装入内存,游标停在查询结果的首部,注意并不是下一行。当打开一个游标时,会完成以下几件事。

    检查连编变量的取值;

    根据联编变量的取值,确定活动集;

    活动集的指针指向第一行。

    紧接上一个例子的代码,打开游标的代码如下:

    open cur_emp('MANAGER');

    上边这表语句表示打开游标’cur_emp‘,然后给游标的’输入参数‘赋值为“MANAGER”。当然这里可以省略“('MANAGER')”,这样表示“输入参数”的值仍然使用其初始值(即SALESMAN).

    (3)读取游标

    当打开一个游标之后,就可以读取游标中的数据了,读取游标就是逐行将结果集中的数据保存到变量中。读取游标使用FETCH...INTO语句,其语法格式:

    FETCH cur_name IN {variable};

    cur_name:要读取的游标的名称;

    variable:一个变量列表或“记录”变量(RECORD类型),Oracle使用记录变量来存储游标中的数据,要比使用变量列表方便得多。

    示例:声明一个检索emp表中雇员信息的游标,然后打开游标,并指定检索职务时MANAGER的雇员信息,接着使用FETCH...INTO语句和WHILE循环语句读取游标中的所有雇员信息,最后输出读取的雇员信息。

    set serveroutput on
    declare
    /*声明游标,检索雇员信息*/
    cursor cur_emp (var_job in varchar2:='SALESMAN')
    is select empno,ename,sal
    from emp
    where job=var_job;
    type record_emp is record --声明一个记录类型(RECORD类型)
    (
    /*定义当前记录的成员变量*/
    var_empno emp.empno%type,
    var_ename emp.ename%type,
    var_sal emp.sal%type
    );
    emp_row record_emp;--声明一个record_emp类型的变量
    begin
    open cur_emp('MANAGER');
    fetch cur_emp into emp_row;--先让指针指向结果集中的第一行
    while cur_emp%found loop
    dbms_output.put_line(emp_row.var_ename||'的编号是'||emp_row.var_empno||',工资是'||emp_row.var_sal);
    fetch cur_emp into emp_row;--让指针指向结果集中的下一行
    end loop;
    close cur_emp;
    end;
    /

    (4)  关闭游标

    当所有的活动集都被检索以后,游标就应该被关闭。PL/SQL程序将告知对于游标的处理已经结束,与游标相关联的资源可以被释放了。这些资源包括用来存储活动集的存储空间,以及用来存储活动集的临时空间。关闭游标的语法格式如下:

    CLOSE cur_name;

    参数cur_name表示要关闭的游标名称。一旦关闭了游标,也就关闭了SELECT操作,释放了占用的内存区。如果再从游标提取数据就是非法的,这样做会产生下面的Oracle错误。

    ORA-1001:lnvalid CUSOR   ---非法游标

    ORA-1002:FETCH out of sequence --超出界限

    类似的,关闭一个已经被关闭的游标也是非法的,这也会触发ORA-1001错误。

    例如:上个例子中,在读取完结果集之后,使用如下的CLOSE语句关闭游标

    SQL> close cur_emp;---关闭游标

    2、隐式游标

    在执行一个SQL语句时,Oracle会自动创建一个隐式游标。这个游标时内存中处理该语句的工作区域。隐式游标主要时处理数据操作语句(如UPDATE、DELETE语句)的执行结果,当然特殊情况下,也可以处理SELECT语句的查询结果。由于饮食游标也有属性,当使用隐式游标的属性时,需要在属性前面加上隐式游标的默认名称——SQL。

    3、游标的属性

    无论时显式游标还是隐式游标,都具有%FOUND、%NOTFOUND、%ROWCOUNT和%ISOPEN4个属性,通过这4个属性可以获知SQL语句的执行结果以及该游标的状态信息。它们描述与游标操作相关的DML语句的执行情况。游标属性只能用在PL/SQL的流程控制语句内,而不能用在SQL语句内。下面对4个游标属性进行讲解:

    (1)是否找到游标%FOUND

    该属性表示当前游标是否指向有效一行,若是则值为TRUE,否则值为FALSE。检查此属性可以判断是否结束游标使用;

    (2)是否没找到游标%NOTDOUND

    该属性与%FOUND属性相类似,但其值恰好相反。

    (3)游标行数%ROWCOUNT

    该属性记录了游标抽取过的记录行数,也可以理解为当前游标所在的行号。这个属性在循环判断中也很有用,使得不必抽取所有记录行就可以终端游标操作;

    (4)游标是否打开%ISOPEN

    该属性表示游标是否处于打开状态。在实际应用中,使用一个游标前第一步往往是检查它得%ISOPEN属性,看其是否已打开,若没有,要打开游标在向下操作。这是防止运行过程中出错得必备一步。

    4、游标变量

    (1)声明游标变量

    游标变量是一种引用类型。当程序运行时,他们可以指向不同得寻存储单元。如果要使用引用类型,首先要声明变量,然后相应得存储单元必须被分配。PL/SQL中得引用类型通过下述的而语法进行声明。

    REF type

    其中type是已经被定义的类型。REF关键字指明新的类型必须是一个指向经过定义的类型的指针。因此,游标可以使用的类型就是REF CURSOR.

    定义一个有游标变量类型的完整语句如下:

    TYPE<类型名> IS REF CURSOR

    RETURN<返回类型>

    其中,<类型名>是新的引用类型的名字,而<返回类型>是一个记录类型,它指明了最终由游标变量返回的选择列表的类型。

    (2)打开游标变量

    如果要将一个游标变量与特定的SELECT语句相关联,需要使用OPEN FOR语句,其语法如下:

    OPEN<游标变量>FOR<SELECT>语句;

    如果游标变量是受限的,则SELECT语句的返回类型必须与游标所限的记录类型匹配,如果不匹配,Oralce会返回错误ORA-6504。
    (3)关闭游标变量

    游标变量的关闭与静态游标的关闭类似,都是使用CLOSE语句。

    5、通过FOR语句循环游标

    在使用隐式游标或显式游标处理具有多行的结果集时,用户可以配合使用FOR语句来完成。在使用FOR语句遍历游标中的数据时,可以把它的计时器看作是一个自动的RECORD类型的变量。

    (1)在FOR 语句中遍历隐式游标中的数据时,通常在关键字IN的后面提供由SELECT语句检索的结果集,在检索结果集的过程中,Oracle系统会自动提供一个隐式的游标SQL;

    (2)在FOR语句中遍历显式游标中的数据时,通常在关键字IN的后面提供游标的名称,其语法格式如下:

    FOR var_auto_record IN cur_name LOOP

    plsqlsentence;

    END LOOP;

    var_auto_record:自动的RECORD类型的变量,可以是任意合法的变量名称;

    cur_name:指定的游标名称;

    plsqlsentence:PL/SQL语句;

  • 相关阅读:
    简单工厂笔记
    P3369 【模板】普通平衡树 Treap树堆学习笔记
    tp5阿里云短信验证码
    centos 安装php
    tp6.0.2开启多应用模式
    linux navicat最新版过期
    git commit之后 取消commit
    服务器重置之后ssh root@报错
    git pull push 每次都需要输入账号和密码
    跨域问题 php
  • 原文地址:https://www.cnblogs.com/TengQiuli/p/14264289.html
Copyright © 2011-2022 走看看