范例:编写不做任何工作的PL/SQL块
BEGIN NULL ; END ; / |
范例:编写一个简单的PL/SQL程序
DECLARE v_num NUMBER ; -- 定义一个变量v_num BEGIN v_num := 30 ; -- 设置v_num的内容 DBMS_OUTPUT.put_line('V_NUM变量的内容是:' || v_num) ; END ; / |
范例:编写PL/SQL块,输入一个雇员编号,而后取得指定的雇员姓名
DECLARE v_eno NUMBER ; v_ename VARCHAR2(10) ; BEGIN v_eno := &empno ; -- 由键盘输入雇员编号 SELECT ename INTO v_ename FROM emp WHERE empno=v_eno ; DBMS_OUTPUT.put_line('编号为:' || v_eno || '雇员的名字为:'|| v_ename) ; END ; / |
范例:定义变量不设置默认值
DECLARE v_result VARCHAR2(30) ; -- 此处没有赋值 BEGIN DBMS_OUTPUT.put_line('v_result的内容〖' || v_result || '〗') ; END ; / |
范例:定义变量
DECLARE v_resultA NUMBER := 100 ; -- 定义一个变量同时赋值 v_resultB NUMBER ; -- 定义一个变量没有设置内容 BEGIN v_resultb := 30 ; -- 没有区分大小写 DBMS_OUTPUT.put_line('计算的结果是:' || (v_resultA + v_resultB) ) ; END ; / |
范例:定义非空变量
DECLARE v_resultA NUMBER NOT NULL := 100 ; -- 定义一个非空变量v_resultA,同时赋值 BEGIN DBMS_OUTPUT.put_line('v_resultA变量内容:' || (v_resultA) ) ; END ; / |
范例:定义常量
DECLARE v_resultA CONSTANT NUMBER NOT NULL := 100 ; -- 定义一个常量同时赋值 BEGIN DBMS_OUTPUT.put_line('v_resultA常量内容:' || (v_resultA) ) ; END ; / |
范例:使用“%TYPE”定义变量
变量与指定的列的类型一致 采用%TYPE%
DECLARE v_eno emp.empno%TYPE ; -- 与empno类型相同 v_ename emp.ename%TYPE ; -- 与ename类型相同 BEGIN DBMS_OUTPUT.put_line('请输入雇员编号:') ; v_eno := &empno ; -- 由键盘输入雇员编号 SELECT ename INTO v_ename FROM emp WHERE empno= v_eno ; DBMS_OUTPUT.put_line('编号为:' || v_eno || '雇员的名字为:'|| v_ename) ; END ; / |
范例:使用ROWTYPE装载
select into讲表中的一行记录设置到ROWTYPE类型的变量v_deptRow中
可以使用v_deptRow. 出字段数据
DECLARE v_deptRow dept%ROWTYPE ; -- 装载一行dept记录 BEGIN SELECT * INTO v_deptRow FROM dept WHERE deptno=10 ; DBMS_OUTPUT.put_line('部门编号:'|| v_deptRow.deptno || ',名称:' || v_deptRow.dname || ',位置:' || v_deptRow.loc) ; END ; / |
范例:通过自定义类型接收一行记录
DECLARE TYPE dept_type IS RECORD ( dno dept.deptno%TYPE , dna dept.dname%TYPE , dlo dept.loc%TYPE) ; -- 定义一个新的类型 v_deptRow dept_type ; -- 装载一行dept记录 BEGIN SELECT * INTO v_deptRow FROM dept WHERE deptno=10 ; DBMS_OUTPUT.put_line('部门编号:'|| v_deptRow.dno || ',名称:' || v_deptRow.dna || ',位置:' || v_deptRow.dlo) ; END ; / |
赋值运算符的主要功能是将一个数值赋予指定数据类型的变量,在之前声明变量时已经使用此运算符,其使用语法如下所示。 变量 := 表达式 ;
范例:使用赋值运算符
将一个数值赋予指定数据类型的变量
DECLARE v_info VARCHAR2(50) := '北京魔乐科技软件学院' ; v_url VARCHAR2(50) ; BEGIN v_url := 'www.mldnjava.cn' ; DBMS_OUTPUT.put_line(v_info) ; DBMS_OUTPUT.put_line(v_url) ; END ; / |
范例:字符串连接 使用||
DECLARE v_info VARCHAR2(50) := '北京魔乐科技软件学院' ; v_url VARCHAR2(50) ; BEGIN v_url := 'www.mldnjava.cn' ; DBMS_OUTPUT.put_line(v_info || ',网址:' || v_url) ; END ; / |
DECLARE v_url VARCHAR2(50) := 'www.mldnjava.cn' ; v_num1 NUMBER := 80 ; v_num2 NUMBER := 30 ; BEGIN IF v_num1 > v_num2 THEN DBMS_OUTPUT.put_line('第1个数字比第2个数字大。') ; END IF ; IF v_url LIKE '%mldn%' THEN DBMS_OUTPUT.put_line('网址之中包含mldn单词。') ; END IF ; END ; / |
范例:观察逻辑运算结果 IF ENDIF
DECLARE v_flag1 BOOLEAN := TRUE ; v_flag2 BOOLEAN := FALSE ; v_flag3 BOOLEAN ; BEGIN IF v_flag1 AND ( NOT v_flag2 ) THEN DBMS_OUTPUT.put_line('v_flag1 AND ( NOT v_flag2 ) = TRUE') ; END IF ; IF v_flag1 OR v_flag3 THEN DBMS_OUTPUT.put_line('v_flag1 OR v_flag3 = TRUE') ; END IF ; IF v_flag1 AND v_flag3 IS NULL THEN DBMS_OUTPUT.put_line('v_flag1 AND v_flag3 的结果为NULL。') ; END IF ; END ; / |
**********数据类型划分*********
范例:定义NUMBER变量
DECLARE v_x NUMBER(3) ; -- 最多只能为3位数字 v_y NUMBER(5,2) ; -- 3位整数,2位小数 BEGIN v_x := -500 ; v_y := 999.88 ; DBMS_OUTPUT.put_line('v_x = ' || v_x) ; DBMS_OUTPUT.put_line('v_y = ' || v_y) ; DBMS_OUTPUT.put_line('加法运算:' || (v_x + v_y)) ; -- 整数 + 浮点数 = 浮点数 END ; / |
范例:验证PLS_INTEGER操作
BINARY_INTEGER PLS_INTERGER -2147483648~2147483647 2进制
相比NUMBER占用范围更小,NUMBER为十进制 所以NUMBER相比性能低
当保存的数超出BINARY_INTEGER PLS_INTERGER范围时会转以NUMBER保存
DECLARE v_pls1 PLS_INTEGER := 100 ; v_pls2 PLS_INTEGER := 200 ; v_result PLS_INTEGER ; BEGIN v_result := v_pls1 + v_pls2 ; DBMS_OUTPUT.put_line('计算结果:' || v_result) ; END ; / |
范例:验证BINARY_DOUBLE操作
BINARY_FLOAT和BINARY_DOUBLE比NUMBER节约空间并且范围更大
使用2进制保存数据,性能高
DECLARE v_float BINARY_FLOAT := 8909.51F ; v_double BINARY_DOUBLE := 8909.51D ; BEGIN v_float := v_float + 1000.16 ; v_double := v_double + 1000.16 ; DBMS_OUTPUT.put_line('BINARY_FLOAT变量内容:' || v_float) ; DBMS_OUTPUT.put_line('BINARY_DOUBLE变量内容:' || v_double) ; END ; / |
范例:观察表示范围的常量内容
DECLARE BEGIN DBMS_OUTPUT.put_line('1、BINARY_FLOAT_MIN_NORMAL = ' || BINARY_FLOAT_MIN_NORMAL) ; DBMS_OUTPUT.put_line('1、BINARY_FLOAT_MAX_NORMAL = ' || BINARY_FLOAT_MAX_NORMAL) ; DBMS_OUTPUT.put_line('1、BINARY_FLOAT_MIN_SUBNORMAL = ' || BINARY_FLOAT_MIN_SUBNORMAL) ; DBMS_OUTPUT.put_line('1、BINARY_FLOAT_MAX_SUBNORMAL = ' || BINARY_FLOAT_MAX_SUBNORMAL) ; DBMS_OUTPUT.put_line('2、BINARY_DOUBLE_MIN_NORMAL = ' || BINARY_DOUBLE_MIN_NORMAL) ; DBMS_OUTPUT.put_line('2、BINARY_DOUBLE_MAX_NORMAL = ' || BINARY_DOUBLE_MAX_NORMAL) ; DBMS_OUTPUT.put_line('2、BINARY_DOUBLE_MIN_SUBNORMAL = ' || BINARY_DOUBLE_MIN_SUBNORMAL) ; DBMS_OUTPUT.put_line('2、BINARY_DOUBLE_MAX_SUBNORMAL = ' || BINARY_DOUBLE_MAX_SUBNORMAL) ; END ; / |
范例:超过范围的计算
DECLARE BEGIN DBMS_OUTPUT.put_line('超过范围计算的结果:' || BINARY_DOUBLE_MAX_NORMAL * BINARY_DOUBLE_MAX_NORMAL) ; DBMS_OUTPUT.put_line('超过范围计算的结果:' || BINARY_DOUBLE_MAX_NORMAL / 0) ; END ; / |
**********字符型*********
范例:观察CHAR和VARCHAR2的区别
char定长 varchar2变长
在oracle中,VARCHAR2就是其他数据库的varchar
DECLARE v_info_char CHAR(10) ; v_info_varchar VARCHAR2(10) ; BEGIN v_info_char := 'MLDN' ; -- 长度不足10个 v_info_varchar := 'java' ; -- 长度不足10个 DBMS_OUTPUT.put_line('v_info_char内容长度:' || LENGTH(v_info_char)) ; DBMS_OUTPUT.put_line('v_info_varchar内容长度:' || LENGTH(v_info_varchar)) ; END ; / |
范例:验证NCHAR和NVARCHAR2
类似CHAR和VARCHAR2,但为UNICODE编码 中英文都为十六进制保存
目的是统一了字符/英文的长度,也浪费了空间
DECLARE v_info_nchar NCHAR(10) ; v_info_nvarchar NVARCHAR2(10) ; BEGIN v_info_nchar := '魔乐科技' ; -- 长度不足10个 v_info_nvarchar := 'java高端培训' ; -- 长度不足10个 DBMS_OUTPUT.put_line('v_info_nchar内容长度:' || LENGTH(v_info_nchar)) ; DBMS_OUTPUT.put_line('v_info_nvarchar内容长度:' || LENGTH(v_info_nvarchar)) ; END ; / |
范例:使用LONG和LONG RAW操作
UTL_RAW.cast_to_raw(‘’字符串)
DECLARE v_info_long LONG ; v_info_longraw LONG RAW ; BEGIN v_info_long := '魔乐科技' ; -- 直接设置字符串 v_info_longraw := UTL_RAW.cast_to_raw('JAVA高端培训') ; -- 将字符串变为RAW DBMS_OUTPUT.put_line('v_info_long内容:' || v_info_long) ; DBMS_OUTPUT.put_line('v_info_longraw内容:' || UTL_RAW.cast_to_varchar2(v_info_longraw)) ; END ; / |
范例:使用ROWID及UROWID
DECLARE v_emp_rowid ROWID ; v_emp_urowid UROWID ; BEGIN SELECT ROWID INTO v_emp_rowid FROM emp WHERE empno=7369 ; -- 取得ROWID SELECT ROWID INTO v_emp_urowid FROM emp WHERE empno=7369 ; -- 取得ROWID DBMS_OUTPUT.put_line('7369雇员的ROWID = ' || v_emp_rowid) ; DBMS_OUTPUT.put_line('7369雇员的UROWID = ' || v_emp_urowid) ; END ; / |
***********日期类型***********
范例:定义DATE型变量
DECLARE v_date1 DATE := SYSDATE ; v_date2 DATE := SYSTIMESTAMP ; v_date3 DATE := '19-9月-1981' ; BEGIN DBMS_OUTPUT.put_line('日期数据:' || TO_CHAR(v_date1,'yyyy-mm-dd hh24:mi:ss')) ; DBMS_OUTPUT.put_line('日期数据:' || TO_CHAR(v_date2,'yyyy-mm-dd hh24:mi:ss')) ; DBMS_OUTPUT.put_line('日期数据:' || TO_CHAR(v_date3,'yyyy-mm-dd hh24:mi:ss')) ; END ; / |
范例:定义TIMESTAMP型变量
DECLARE v_timestamp1 TIMESTAMP := SYSDATE ; v_timestamp2 TIMESTAMP := SYSTIMESTAMP ; v_timestamp3 TIMESTAMP := '19-9月-1981' ; BEGIN DBMS_OUTPUT.put_line('日期数据:' || v_timestamp1) ; DBMS_OUTPUT.put_line('日期数据:' || v_timestamp2) ; DBMS_OUTPUT.put_line('日期数据:' || v_timestamp3) ; END ; / |
范例:验证TIMESTAMP WITH TIME ZONE
DECLARE v_timestamp TIMESTAMP WITH TIME ZONE := SYSTIMESTAMP ; BEGIN DBMS_OUTPUT.put_line(v_timestamp) ; END ; / |
范例:验证TIMESTAMP WITH LOCAL TIME ZONE
DECLARE v_timestamp TIMESTAMP WITH LOCAL TIME ZONE := SYSTIMESTAMP ; BEGIN DBMS_OUTPUT.put_line(v_timestamp) ; END ; / |
范例:定义INTERVAL YEAR TO MONTHS类型变量
DECLARE v_interval INTERVAL YEAR(3) TO MONTH := INTERVAL '27-09' YEAR TO MONTH ; BEGIN DBMS_OUTPUT.put_line('时间间隔:' || v_interval) ; DBMS_OUTPUT.put_line('当前时间戳 + 时间间隔:' || (SYSTIMESTAMP + v_interval)) ; DBMS_OUTPUT.put_line('当前日期 + 时间间隔:' || (SYSDATE + v_interval)) ; END ; / |
范例:定义INTERVAL DAY TO SECOND类型变量
DECLARE v_interval INTERVAL DAY(6) TO SECOND (3) := INTERVAL '8 18:19:27.367123909' DAY TO SECOND; BEGIN DBMS_OUTPUT.put_line('时间间隔:' || v_interval) ; DBMS_OUTPUT.put_line('当前时间戳 + 时间间隔:' || (SYSTIMESTAMP + v_interval)) ; DBMS_OUTPUT.put_line('当前日期 + 时间间隔:' || (SYSDATE + v_interval)) ; END ; / |
范例:定义布尔型变量
DECLARE v_flag BOOLEAN ; BEGIN v_flag := true ; IF v_flag THEN DBMS_OUTPUT.put_line('条件满足。') ; END IF ; END ; / |
范例:定义NUMBER子类型
DECLARE SUBTYPE score_subtype IS NUMBER(5,2) NOT NULL ; v_score score_subtype := 99.35 ; BEGIN DBMS_OUTPUT.put_line('成绩为:' || v_score) ; END ; / |
范例:定义VARCHAR2子类型
DECLARE SUBTYPE string_subtype IS VARCHAR2(200) ; v_company string_subtype ; BEGIN v_company := '北京魔乐科技软件学院(www.mldnjava.cn)' ; DBMS_OUTPUT.put_line(v_company) ; END ; / |
**********分支结构***********
范例:IF语句
DECLARE v_countResult NUMBER ; BEGIN SELECT COUNT(empno) INTO v_countResult FROM emp ; IF v_countResult > 10 THEN DBMS_OUTPUT.put_line('EMP表的记录大于10条。') ; END IF ; END ; / |
范例:IF…ELSE语句
DECLARE v_countResult NUMBER ; BEGIN SELECT COUNT(deptno) INTO v_countResult FROM dept ; IF v_countResult > 10 THEN DBMS_OUTPUT.put_line('DEPT表的记录大于10条。') ; ELSE DBMS_OUTPUT.put_line('DEPT表的记录小于10条。') ; END IF ; END ; / |
范例:IF…ELSIF…ELSE语句
DECLARE v_countResult NUMBER ; BEGIN SELECT COUNT(empno) INTO v_countResult FROM emp ; IF v_countResult > 10 THEN DBMS_OUTPUT.put_line('EMP表的记录大于10条。') ; ELSIF v_countResult < 10 THEN DBMS_OUTPUT.put_line('EMP表的记录小于10条。') ; ELSE DBMS_OUTPUT.put_line('EMP表的记录等于10条。') ; END IF ; END ; / |
范例:查询emp表的工资,输入员工编号,根据编号查询工资,如果工资高于3000元,则显示高工资,如果工资大于2000元,则显示中等工资,如果工资小于2000元,则显示低工资。
DECLARE v_empSal emp.sal%TYPE ; -- 定义变量与emp.sal字段类型相同 v_empName emp.ename%TYPE ; -- 定义变量与emp.ename字段类型相同 v_eno emp.empno%TYPE ; -- 定义变量与emp.empno字段类型相同 BEGIN v_eno := &inputEmpno; -- 用户输入要查找的雇员编号 -- 根据输入的雇员编号查找雇员姓名及工资 SELECT ename,sal INTO v_empName,v_empSal FROM emp WHERE empno=v_eno; IF v_empSal > 3000 THEN -- 判断 DBMS_OUTPUT.put_line(v_empName || '的工资属于高工资!') ; ELSIF v_empSal > 2000 THEN -- 判断 DBMS_OUTPUT.put_line(v_empName || '的工资属于中等工资!') ; ELSE DBMS_OUTPUT.put_line(v_empName || '的工资属于低工资!') ; END IF; END; / |
范例:用户输入一个雇员编号,根据它所在的部门给上涨工资,规则:
· 10部门上涨10%,20上涨20%,30上涨30%;
· 但是要求最高不能超过5000,超过5000就停留在5000。
DECLARE v_empSal emp.sal%TYPE ; -- 定义变量与emp.sal字段类型相同 v_dno emp.deptno%TYPE ; -- 定义变量与emp.deptno字段类型相同 v_eno emp.empno%TYPE ; -- 定义变量与emp.empno字段类型相同 BEGIN v_eno := &inputEmpno; -- 用户输入要查找的雇员编号 SELECT deptno,sal INTO v_dno, v_empSal FROM emp WHERE empno = v_eno ; IF v_dno = 10 THEN IF v_empSal * 1.1 > 5000 THEN UPDATE emp SET sal=5000 WHERE empno=v_eno; ELSE UPDATE emp SET sal=sal*1.1 WHERE empno=v_eno; END IF; ELSIF v_dno = 20 THEN IF v_empSal * 1.2 > 5000 THEN UPDATE emp SET sal =5000 WHERE empno=v_eno; ELSE UPDATE emp SET sal=sal*1.2 WHERE empno=v_eno; END IF; ELSIF v_dno = 30 THEN IF v_empSal * 1.3 > 5000 THEN UPDATE emp SET sal=5000 WHERE empno=v_eno; ELSE UPDATE emp SET sal=sal*1.3 WHERE empno=v_eno; END IF; ELSE null; END IF; END; / |
范例:正则验证
DECLARE v_str VARCHAR2(50) := '123' ; BEGIN IF REGEXP_LIKE(v_str,'^d+$') THEN DBMS_OUTPUT.put_line('正则验证通过。') ; END IF ; END ; / |
范例:验证AND操作符
BEGIN IF 'MLDN' = 'MLDN' AND 100 = 100 THEN DBMS_OUTPUT.put_line('结果为TRUE,满足条件!') ; END IF ; END; / |
范例:验证BETWEEN…AND
BEGIN IF TO_DATE('1983-09-19','yyyy-mm-dd') BETWEEN TO_DATE('1980-01-01','yyyy-mm-dd') AND TO_DATE('1989-12-31','yyyy-mm-dd') THEN DBMS_OUTPUT.put_line('您俗称80后!') ; END IF ; END; / |
范例:验证IN操作符
BEGIN IF 10 IN (10,20,30) THEN DBMS_OUTPUT.put_line('数据已成功查找到') ; END IF ; END; / |
范例:验证IS NULL
DECLARE v_temp BOOLEAN ; -- 定义布尔变量,没有设置内容 BEGIN IF v_temp IS NULL THEN DBMS_OUTPUT.put_line('v_temp变量的内容是null。') ; END IF ; END; / |
范例:验证LIKE操作符
BEGIN IF 'www.mldnjava.cn' LIKE '%mldn%' THEN DBMS_OUTPUT.put_line('可以查找到字符串:mldn。') ; END IF ; END; / |
范例:验证NOT操作符
BEGIN IF NOT FALSE THEN DBMS_OUTPUT.put_line('条件满足,FALSE变为TRUE。') ; END IF ; END; / |
范例:
BEGIN IF 'MLDN' = 'LXH' OR 10 = 10 THEN DBMS_OUTPUT.put_line('有一个条件满足,返回TRUE。') ; END IF ; END; / |
范例:使用CASE语句判断数值
DECLARE v_choose NUMBER := 1 ; BEGIN CASE v_choose WHEN 0 THEN DBMS_OUTPUT.put_line('您选择的是第0项。') ; WHEN 1 THEN DBMS_OUTPUT.put_line('您选择的是第1项。') ; ELSE DBMS_OUTPUT.put_line('没有选项满足。') ; END CASE ; END ; / |
范例:使用CASE进行多条件判断
DECLARE v_salary emp.sal%TYPE ; v_eno emp.empno%TYPE ; BEGIN v_eno := &inputEmpno ; SELECT sal INTO v_salary FROM emp WHERE empno=v_eno ; CASE WHEN v_salary >= 3000 THEN DBMS_OUTPUT.put_line('雇员:' || v_eno || '的收入为高工资。') ; WHEN v_salary >= 2000 AND v_salary <3000 THEN DBMS_OUTPUT.put_line('雇员:' || v_eno || '的收入为中等工资。') ; ELSE DBMS_OUTPUT.put_line('雇员:' || v_eno || '的收入为低工资。') ; END CASE ; END ; / |
范例:输入雇员编号,根据雇员的职位进行工资提升,提升要求如下
· 如果职位是办事员(CLERK),工资增长5%;
· 如果职位是销售人员(SALESMAN),工资增长8%;
· 如果职位为经理(MANAGER),工资增长10%;
· 如果职位为分析员(ANALYST),工资增长20%;
· 如果职位为总裁(PRESIDENT),工资不增长。
DECLARE v_job emp.job%TYPE ; v_eno emp.empno%TYPE ; BEGIN v_eno := &inputEmpno ; SELECT job INTO v_job FROM emp WHERE empno=v_eno ; CASE v_job WHEN 'CLERK' THEN UPDATE emp SET sal=sal*1.05 WHERE empno=v_eno ; WHEN 'SALESMAN' THEN UPDATE emp SET sal=sal*1.08 WHERE empno=v_eno ; WHEN 'MANAGER' THEN UPDATE emp SET sal=sal*1.10 WHERE empno=v_eno ; WHEN 'ANALYST' THEN UPDATE emp SET sal=sal*1.20 WHERE empno=v_eno ; ELSE DBMS_OUTPUT.put_line('雇员:' || v_eno || '工资不具备上涨资格!') ; END CASE ; END ; / |
范例:使用LOOP循环
EXIT WHEN结束循环
DECLARE v_i NUMBER := 1 ; -- 定义一个变量,用于循环 BEGIN LOOP DBMS_OUTPUT.put_line('v_i = ' || v_i) ; EXIT WHEN v_i >= 3 ; v_i := v_i + 1 ; END LOOP ; END ; / |
范例:使用WHILE…LOOP循环
DECLARE v_i NUMBER := 1 ; -- 定义一个变量,用于循环 BEGIN WHILE (v_i <= 3) LOOP DBMS_OUTPUT.put_line('v_i = ' || v_i) ; v_i := v_i + 1 ; END LOOP ; END ; / |
范例:使用FOR循环
DECLARE v_i NUMBER := 1 ; -- 定义一个变量,用于循环 BEGIN FOR v_i IN 1 .. 3 LOOP DBMS_OUTPUT.put_line('v_i = ' || v_i) ; END LOOP ; END ; / |
范例:使用REVERSE操作
DECLARE v_i NUMBER := 1 ; -- 定义一个变量,用于循环 BEGIN FOR v_i IN REVERSE 1 .. 3 LOOP DBMS_OUTPUT.put_line('v_i = ' || v_i) ; END LOOP ; END ; / |
范例:使用EXIT结束循环操作
DECLARE v_i NUMBER := 1 ; -- 定义一个变量,用于循环 BEGIN FOR v_i IN 1 .. 10 LOOP IF v_i = 3 THEN -- 当v_i变量增长到3时结束循环 EXIT ; END IF ; DBMS_OUTPUT.put_line('v_i = ' || v_i) ; END LOOP ; END ; / |
范例:使用CONTINUE控制循环操作(结束当前的循环)
DECLARE v_i NUMBER := 1 ; -- 定义一个变量,用于循环 BEGIN FOR v_i IN 1 .. 10 LOOP IF MOD(v_i,2) = 0 THEN -- 为偶数的时候不执行后续方法体 CONTINUE ; END IF ; DBMS_OUTPUT.put_line('v_i = ' || v_i) ; END LOOP ; END ; / |
范例:使用GOTO进行跳转
DECLARE v_result NUMBER := 1; BEGIN FOR v_result IN 1 .. 10 LOOP IF v_result = 2 THEN GOTO endPoint ; END IF ; DBMS_OUTPUT.put_line('v_result = ' || v_result) ; END LOOP ; <<endPoint>> DBMS_OUTPUT.put_line('FOR循环提前结束。') ; END ; / |
范例:定义内部程序块
DECLARE v_x NUMBER := 30 ; -- 此为全局变量 BEGIN DECLARE v_x VARCHAR2(40) := 'MLDNJAVA' ; -- 此为局部变量,只能在内部程序块中使用 v_y NUMBER := 20 ; BEGIN DBMS_OUTPUT.put_line('内部程序块输出:v_x = ' || v_x) ; DBMS_OUTPUT.put_line('内部程序块输出:v_y = ' || v_y) ; END ; DBMS_OUTPUT.put_line('外部程序块输出:v_x = ' || v_x) ; END ; / |
范例:程序语法错误
DECLARE v_result NUMBER := 1 ; BEGIN IF v_result = 1-- 此处语法有错误,缺少THEN DBMS_OUTPUT.put_line('条件满足。') ; END IF ; END ; / |
范例:运行时异常
DECLARE v_result NUMBER ; BEGIN v_result := 10/0 ; -- 被除数为0 END ; / |
范例:处理被除数为零异常
DECLARE v_result NUMBER ; BEGIN v_result := 10/0 ; -- 被除数为0 DBMS_OUTPUT.put_line('异常之后的代码将不再执行!') ; EXCEPTION WHEN zero_divide THEN DBMS_OUTPUT.put_line('被除数不能为零。') ; DBMS_OUTPUT.put_line('SQLCODE = ' || SQLCODE) ; END ; / |
范例:处理赋值异常
DECLARE v_varA VARCHAR2(1) ; v_varB VARCHAR2(4) := 'java' ; BEGIN v_varA := v_varB ; -- 错误的赋值 DBMS_OUTPUT.put_line('异常之后的代码将不再执行!') ; EXCEPTION WHEN value_error THEN DBMS_OUTPUT.put_line('数据赋值错误。') ; DBMS_OUTPUT.put_line('SQLCODE = ' || SQLCODE) ; END ; / |
范例:处理SQL异常 —— 找不到数据
DECLARE v_eno emp.empno%TYPE ; v_ename emp.ename%TYPE ; BEGIN v_eno := &empno ; -- 由键盘输入雇员编号 SELECT ename INTO v_ename FROM emp WHERE empno=v_eno ; DBMS_OUTPUT.put_line('编号为:' || v_eno || '雇员的名字为:' || v_ename) ; EXCEPTION WHEN no_data_found THEN DBMS_OUTPUT.put_line('没有这个雇员!') ; END ; / |
范例:处理SQL异常 —— 返回多条结果
DECLARE v_dno emp.deptno%TYPE ; v_ename emp.ename%TYPE ; BEGIN v_dno := &deptno ; -- 由键盘输入部门编号 SELECT ename INTO v_ename FROM emp WHERE deptno=v_dno ; EXCEPTION WHEN too_many_rows THEN DBMS_OUTPUT.put_line('返回的数据过多!') ; DBMS_OUTPUT.put_line('SQLCODE = ' || SQLCODE) ; END ; / |
范例:使用others来捕获所有异常
DECLARE v_result NUMBER ; v_title VARCHAR2(50) := 'www.mldnjava.cn' ; BEGIN v_result := v_title ;-- 此处出现异常 EXCEPTION WHEN others THEN DBMS_OUTPUT.put_line('返回的数据过多!') ; DBMS_OUTPUT.put_line('SQLCODE = ' || SQLCODE) ; DBMS_OUTPUT.put_line('SQLERRM = ' || SQLERRM) ; END ; / |
范例:使用用户定义异常
DECLARE v_data NUMBER ; v_myexp EXCEPTION ; BEGIN v_data := &inputData ; IF v_data > 10 AND v_data < 100 THEN RAISE v_myexp ; -- 抛出异常 END IF ; EXCEPTION WHEN others THEN DBMS_OUTPUT.put_line('输入数据有错误!') ; DBMS_OUTPUT.put_line('SQLCODE = ' || SQLCODE) ; DBMS_OUTPUT.put_line('SQLERRM = ' || SQLERRM) ; END ; / |
范例:设置异常代码
DECLARE v_data NUMBER ; v_myexp EXCEPTION ; PRAGMA EXCEPTION_INIT(v_myexp , -20789) ; BEGIN v_data := &inputData ; IF v_data > 10 AND v_data < 100 THEN RAISE v_myexp ; -- 抛出异常 END IF ; EXCEPTION WHEN v_myexp THEN DBMS_OUTPUT.put_line('输入数据有错误!') ; DBMS_OUTPUT.put_line('SQLCODE = ' || SQLCODE) ; DBMS_OUTPUT.put_line('SQLERRM = ' || SQLERRM) ; END ; / |
范例:绑定已有的错误号
DECLARE v_myexp EXCEPTION ; v_input_rowid VARCHAR2(18) ; PRAGMA EXCEPTION_INIT(v_myexp , -01410) ; BEGIN v_input_rowid := '&inputRowid' ; -- 输入一个ROWID IF LENGTH(v_input_rowid) <> 18 THEN RAISE v_myexp ; END IF ; EXCEPTION WHEN v_myexp THEN DBMS_OUTPUT.put_line('SQLCODE = ' || SQLCODE) ; DBMS_OUTPUT.put_line('SQLERRM = ' || SQLERRM) ; END ; / |
范例:构建动态异常
DECLARE v_data NUMBER ; v_myexpEXCEPTION ; -- 定义了一个异常变量 PRAGMA EXCEPTION_INIT(v_myexp , -20789) ; BEGIN v_data := &inputData ; -- 输入数据 IF v_data > 10 AND v_data < 100 THEN RAISE_APPLICATION_ERROR(-20789 , '输入数字不能在10 ~ 100之间!') ; END IF ; EXCEPTION WHEN v_myexp THEN -- 出现指定的异常 DBMS_OUTPUT.put_line('输入数据有错误!') ; DBMS_OUTPUT.put_line('SQLCODE = ' || SQLCODE) ; DBMS_OUTPUT.put_line('SQLERRM = ' || SQLERRM) ; END ; / |
范例:不声明异常变量,直接构建异常,同时使用others捕获
DECLARE v_data NUMBER ; v_myexp EXCEPTION ; -- 定义了一个异常变量 BEGIN v_data := &inputData ; -- 输入数据 IF v_data > 10 AND v_data < 100 THEN RAISE_APPLICATION_ERROR(-20789 , '输入数字不能在10 ~ 100之间!') ; END IF ; EXCEPTION WHEN others THEN -- 出现指定的异常 DBMS_OUTPUT.put_line('输入数据有错误!') ; DBMS_OUTPUT.put_line('SQLCODE = ' || SQLCODE) ; DBMS_OUTPUT.put_line('SQLERRM = ' || SQLERRM) ; END ; / |
范例:使用PL/SQL增加部门信息
DECLARE v_dno dept.deptno%TYPE ; -- 部门编号 v_dna dept.dname%TYPE ; -- 部门名称 v_dloc dept.loc%TYPE ; -- 部门位置 v_deptCount NUMBER ; -- 保存COUNT()函数结果 BEGIN v_dno := &inputDeptno ; -- 输入部门编号 v_dna := '&inputDname' ; -- 输入部门名称 v_dloc := '&inputLoc' ; -- 接收部门位置 -- 统计要增加的部门编号在dept表中的信息数量,如果返回0表示没有此部门 SELECT COUNT(deptno) INTO v_deptCount FROM dept WHERE deptno=v_dno ; IF v_deptCount > 0 THEN -- 部门存在 RAISE_APPLICATION_ERROR(-20888 , '此部门编号已存在,请重新输入!') ; ELSE -- 部门不存在 INSERT INTO dept(deptno,dname,loc) VALUES (v_dno,v_dna,v_dloc) ; DBMS_OUTPUT.put_line('新部门增加成功!') ; COMMIT ; END IF ; EXCEPTION WHEN others THEN DBMS_OUTPUT.put_line(SQLERRM) ; ROLLBACK ; END ; / |