PL/SQL基本程序结构和语句(三)

发布于:2022-12-13 ⋅ 阅读:(467) ⋅ 点赞:(0)

目录

1.PL/SQL的程序框架

2.条件结构

(1)IF-THEN语句

(2)IF-THEN-ELSE语句

(3)IF-THEN-ELSIF-THEN-ELSE语句

3.循环体结构

(1)LOOP-EXIT-END语句

(2)LOOP-EXIT-WHEN-END循环

(3)WHILE-LOOP-END循环 

(4)FOR-IN-LOOP-END循环

4.选择和跳转语句

(1)CASE语句

(2)GOTO语句

5.异常处理

(1)预定义异常

(2)用户自定义异常


PL/SQL基础知识点(一)

PL/SQL变量,常量和数据类型(二)

1.PL/SQL的程序框架

[DELCARE]
--声明部分
BEGIN
--执行部分
[EXCEPTION]
--异常处理部分
END

2.条件结构

(1)IF-THEN语句

IF<表达式>THEN

       <PL/SQL语句>;

END IF;

例子:

已建好的表XSB(学生表)

根据上面的表进行操作:

--现在要求输出XSB表中的分数SCORE大于50的学生人数:

--设置输出缓冲
SET SERVEROUTPUT ON;
DECLARE 
    v_num NUMBER(3);
BEGIN
    SELECT COUNT(*) INTO v_num
        FROM XSB
        WHERE score>50;
    IF v_num!=0 THEN
        DBMS_OUTPUT.PUT_LINE('总学法>50: '||TO_CHAR(v_num));
    END IF;
END;

(2)IF-THEN-ELSE语句

 IF<表达式>THEN

       <PL/SQL语句1>;

ELSE

        <PL/SQL语句2>;

END IF;

例子:还是使用上面学生表

求学生的平均学分是否大于50

SET SERVEROUTPUT ON;
DECLARE
    v_avg number(4,2);
BEGIN
    SELECT AVG(score) INTO v_avg
        FROM XSB;
    IF v_avg>50 THEN
        dbms_output.put_line('平均学分大于50');
    ELSE
        dbms_output.put_line('平均学分小于50');
    END IF;
END; 

(3)IF-THEN-ELSIF-THEN-ELSE语句

 IF<表达式1>THEN

       <PL/SQL语句1>;

ELSIF<表达式2>THEN

        <PL/SQL语句2>

ELSE

        <PL/SQL语句3>;

END IF;

例子:求x^+4x+3=0

SET SERVEROUTPUT ON;
declare
    a number;
    b number;
    c number;
    x1 number;
    x2 number;
    d number;
BEGIN 
    a:=1;
    b:=4;
    c:=3;
    d:=b*b-4*a*c;
    IF a=0 THEN
        x1:=-c/b;
        DBMS_OUTPUT.PUT_LINE('只有一个平方根: '||to_char(x1));
    ELSIF d<0 THEN
        DBMS_OUTPUT.PUT_LINE('没有算术平方根');
    ELSE
        x1:=(-b+sqrt(d))/(2*a);
        x2:=(-b-sqrt(d))/(2*a);
        DBMS_OUTPUT.PUT_LINE('x1 = '||to_char(x1));
        DBMS_OUTPUT.PUT_LINE('x2 = '||to_char(x2));
    END IF;
END;
 

3.循环体结构

(1)LOOP-EXIT-END语句

LOOP

        <循环体>

        IF <条件表达式>THEN

                EXIT;

        END IF;

END LOOP

 --求10的阶乘
SET SERVEROUTPUT ON;
DECLARE
    fact number:=1;
    cnt number:=2;
BEGIN
    LOOP
        fact:=fact*cnt;
        cnt:=cnt+1;
        IF cnt>10 THEN
            EXIT;
        END IF;
    END LOOP;
    DBMS_OUTPUT.PUT_LINE('10! = '||to_char(fact));
END;

(2)LOOP-EXIT-WHEN-END循环

 LOOP

        <循环体>

        EXIT WHEN<条件表达式>

END LOOP;

例子:求10的阶乘。 

SET SERVEROUTPUT ON;
DECLARE 
    n number:=1;
    cnt number:=2;
BEGIN
    LOOP
        n:=n*cnt;
        cnt:=cnt+1;
        EXIT WHEN cnt=11;
    END LOOP;
    DBMS_OUTPUT.PUT_LINE('10! = '||TO_CHAR(n));
END;
 

(3)WHILE-LOOP-END循环 

WHILE<条件表达式>

        LOOP

                <循环体>

        END LOOP;

例子:求10的阶乘。 

 SET SERVEROUTPUT ON;
DECLARE 
    n number:=1;
    cnt number:=2;
BEGIN
    WHILE cnt<=10
    LOOP
        n:=n*cnt;
        cnt:=cnt+1;
    END LOOP;
    DBMS_OUTPUT.PUT_LINE('10! = '||TO_CHAR(n));
END;

(4)FOR-IN-LOOP-END循环

FOR<循环变量名> IN <变量初始值>..<变量终值>

        LOOP

                <循环体>

        END LOOP;

例子:求10的阶乘。 

SET SERVEROUTPUT ON;
DECLARE 
    n number:=1;
    cnt number:=2;
BEGIN
    FOR cnt IN 2..10
        LOOP
            n:=n*cnt;
        END LOOP;
    DBMS_OUTPUT.PUT_LINE('10! = '||TO_CHAR(n));
END;
 

4.选择和跳转语句

(1)CASE语句

CASE <变量名>

        WHEN <值1> THEN <语句1>

        WHEN <值2> THEN <语句2>

        ...

        WHEN <值n> THEN <语句n>

END CASE;

例子:根据上面创建的表,通过学生号查找学生的专业。

SET SERVEROUTPUT ON;
DECLARE 
    v_key xsb.sid%TYPE;
    v_result varchar2(20);
BEGIN 
    SELECT sid INTO v_key
        FROM XSB
        WHERE sname='王林';
    CASE v_key
        WHEN '151101' THEN v_result:='计算机专业';
        WHEN '151102' THEN v_result:='机器工程专业';
        WHEN '151103' THEN v_result:='通信工程专业';
    ELSE
        v_result:='nothing';
    END CASE;
    DBMS_OUTPUT.PUT_LINE('专业: '||to_char(v_result));
END;
 

(2)GOTO语句

PL/SQL提供的GOTO语句,实现将执行流程转移到标号指定的位置

格式:GOTO<标号>

GOTO语句后面的语句标号必须符合标识符的规则。

格式:<<标号>>语句

例子:使用上面创建的表,手动输入学生的信息到信息表中。 

SET SERVEROUTPUT ON;
DECLARE
    id XSB.SID%TYPE;
    name XSB.SNAME%TYPE;
    sex XSB.SEX%TYPE;
    birthday XSB.BIRTHDAY%TYPE;
    profession XSB.PROFESSION%TYPE;
    score XSB.SCORE%TYPE;
    cnt number:=0;
BEGIN
        LOOP
            INSERT INTO XSB VALUES('&id','&name','&sex','&birthday','&profession','&score');
            cnt:=cnt+1;
            IF cnt>1 THEN
                GOTO loop_end;
            END IF;
        END LOOP;
    <<loop_end>>
    DBMS_OUTPUT.PUT_LINE('insert successful!');
END;

5.异常处理

(1)预定义异常

预定义异常是由运行系统产生的。

PL/SQL中常见的异常
异常 说明
zero_divide 除零发生的异常,例如:当发生v_num/0时,那么会产生除零异常。
no_date_found 如果一个select语句试图基于其条件检索数据,此异常表示不存在满足条件的数据行。
too_many_rows 由于隐式游标每次只能检索一行数据,使用隐式游标时,这个异常可检测到多行数据存在。
dup_val_on_index 如果某索引已有某键列值,若还要在该索引中创建该键码值索引时,出现此异常。例如:假设一个药店系统以发票号为键码,当某个应用程序准备创建一个重复的发票号时,那么会产生此异常。
value_error 此异常表示指定目标域的长度小于待放入其中的数据长度,例如:将“ABCDEFG”字符串放入到定义为“varchar2(3)”中时,那么将会产生此异常。
case_not_found 在case语句中出现不匹配的when语句时,出现此异常。

例子1:除零发生的异常。

SET SERVEROUTPUT ON;
DECLARE
    v_value number(2):=1;
    v_number number(2):=0;
    v_result number(2);
BEGIN
    v_result:=v_value/v_number;
    EXCEPTION
        WHEN ZERO_DIVIDE THEN
            DBMS_OUTPUT.PUT_LINE('DIVIDE ZERO');
END;

例子2:类型转换的错误处理。

SET SERVEROUTPUT ON;
DECLARE
    v_value number(5);
    v_result char(5):='6y';
BEGIN
    v_value:=to_char(v_result);
    EXCEPTION
        WHEN VALUE_ERROR THEN
            DBMS_OUTPUT.PUT_LINE('CONVERT TYPE ERROR');
END; 

例子3:联合异常的处理。

 SET SERVEROUTPUT ON;
DECLARE
    v_value XSB.SID%TYPE;
BEGIN
    SELECT sid INTO v_value
        FROM XSB
        WHERE sid='&id';
    DBMS_OUTPUT.PUT_LINE('information; '||to_char(v_value));
    EXCEPTION
        WHEN TOO_MANY_ROWS THEN
            DBMS_OUTPUT.PUT_LINE('This is too many rows');
        WHEN NO_DATA_FOUND THEN
            DBMS_OUTPUT.PUT_LINE('not found data');
END;

 

(2)用户自定义异常

 EXCEPTION

        WHEN 异常名  THEN

                语句块1;

        WHEN 异常名  THEN

                语句块2;

        [WHEN OTHERS THEN

                语句块3]

END;

例子:统计表中的学生数和给定的最大上限进行比较。

SET SERVEROUTPUT ON;
DECLARE
    overNumber EXCEPTION;
    v_numLen number(2):=0;
    v_maxvalue number(2):=10;
BEGIN
    --统计表中的学生数
    SELECT count(*) INTO v_numLen
        FROM XSB;
    --使用REAISE调用异常处理
    IF v_numLen>v_maxvalue THEN
        RAISE overNumber;
    END IF;
    EXCEPTION
        WHEN overNumber THEN
            DBMS_OUTPUT.PUT_LINE('v_numLen: '||to_char(v_numLen)
            ||'  v_maxValue: '||to_char(v_maxvalue));
END;

可以使用多个WHEN捕获多个异常,还可以结合系统预定义的异常进行处理。 

EXCEPTION

        --当出现异常1或者异常2的时候执行语句

        WHEN 异常1 OR 异常2 THEN

        ……

        --当出现异常3的之后执行语句

        WHEN 异常3 THEN

END;

使用OTHERS处理异常

SET SERVEROUTPUT ON;
DECLARE
    v_value XSB.SID%TYPE;
BEGIN
    SELECT sid INTO v_value
        FROM XSB
        WHERE sid='&id';
    DBMS_OUTPUT.PUT_LINE('information; '||to_char(v_value));
    EXCEPTION
        WHEN TOO_MANY_ROWS THEN
            DBMS_OUTPUT.PUT_LINE('This is too many rows');
        WHEN OTHERS THEN
            DBMS_OUTPUT.PUT_LINE('implement OTHERS');
END;

补充:也可以将上面的OTHERS中的语句块换成下面的语句执行。

(1)SQLCODE:报告当前错误的代码,如果是用户自定义的异常,那么返回“1”;

(2)SQLERRM:返回的是当前错误的信息。 


SET SERVEROUTPUT ON;
DECLARE
    v_value XSB.SID%TYPE;
BEGIN
    SELECT sid INTO v_value
        FROM XSB
        WHERE sid='&id';
    DBMS_OUTPUT.PUT_LINE('information; '||to_char(v_value));
    EXCEPTION
        WHEN TOO_MANY_ROWS THEN
            DBMS_OUTPUT.PUT_LINE('This is too many rows');
        WHEN OTHERS THEN
            DBMS_OUTPUT.PUT_LINE('The SQLCODE is: '||SQLCODE);
            DBMS_OUTPUT.PUT_LINE('The SQLERRM is: '||SQLERRM);
END;