目录
- [DELCARE]
- --声明部分
- BEGIN
- --执行部分
- [EXCEPTION]
- --异常处理部分
- END
IF<表达式>THEN
; 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;
IF<表达式>THEN
; ELSE
; 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;
IF<表达式1>THEN
; ELSIF<表达式2>THEN
ELSE
; 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;
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;
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;
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;
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;
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;
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;
<>
DBMS_OUTPUT.PUT_LINE('insert successful!');
END;
预定义异常是由运行系统产生的。
异常 | 说明 |
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;
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;