分回退插入操作,然后显示相应的错误信息。
【训练2】 使用RAISE_APPLICATION_ERROR函数引发系统异常。 Sql代码
1. SET SERVEROUTPUT ON 2. DECLARE
3. New_no NUMBER(10); 4. BEGIN
5. New_no:=6789;
6. INSERT INTO emp(empno,ename) 7. VALUES(new_no, 'JAMES');
8. IF new_no<7000 THEN 9. ROLLBACK;
10. RAISE_APPLICATION_ERROR(-20001, '编号小于7000的下限!'); 11. END IF;
12. IF new_no>8000 THEN
13. ROLLBACK;
14. RAISE_APPLICATION_ERROR (-20002, '编号大于8000的下限!'); 15. END IF; 16. END;
执行结果为: Sql代码
1. DECLARE 2. *
3. ERROR 位于第 1 行:
4. ORA-20001: 编号小于7000的下限! 5. ORA-06512: 在line 9
说明:在本训练中,使用RAISE_APPLICATION_ERROR引发自定义异常,并以系统错误的方式进行显示。错误编号为20001和20002。
注意:同上一个训练比较,此种方法不需要事先定义异常,可直接引发。
可以参考下面的程序片断将出错信息记录到表中,其中,errors为记录错误信息的表,SQLCODE为发生异常的错误编号,SQLERRM为发生异常的错误信息。 DECLARE
v_error_code NUMBER;
v_error_message VARCHAR2(255); BEGIN ...
EXCEPTION ...
WHEN OTHERS THEN
v_error_code := SQLCODE ;
v_error_message := SQLERRM ; INSERT INTO errors
VALUES(v_error_code, v_error_message); END;
【练习1】修改雇员的工资,通过引发异常控制修改范围在600~6000之间。 阶段训练
【训练1】 将雇员从一个表复制到另一个表。 步骤1:创建一个结构同EMP表一样的新表EMP1:
CREATE TABLE emp1 AS SELECT * FROM SCOTT.EMP WHERE 1=2; 步骤2:通过指定雇员编号,将雇员由EMP表移动到EMP1表: Sql代码
1. SET SERVEROUTPUT ON 2. DECLARE
3. v_empno NUMBER(5):=7788; 4. emp_rec emp%ROWTYPE; 5. BEGIN
6. SELECT * INTO emp_rec FROM emp WHERE empno=v_empno; 7. DELETE FROM emp WHERE empno=v_empno; 8. INSERT INTO emp1 VALUES emp_rec; 9. IF SQL%FOUND THEN 10. COMMIT;
11. DBMS_OUTPUT.PUT_LINE('雇员复制成功!'); 12. ELSE
13. ROLLBACK;
14. DBMS_OUTPUT.PUT_LINE('雇员复制失败!'); 15. END IF; 16. END;
执行结果为: 雇员复制成功!
PL/SQL 过程已成功完成。
步骤2:显示复制结果:
SELECT empno,ename,job FROM emp1; 执行结果为: Sql代码
1. EMPNO ENAME JOB
2. ------------- -------------- ---------------- 3. 7788 SCOTT ANALYST
说明:emp_rec变量是根据emp表定义的记录变量,SELECT...INTO...语句将整个记录传给该变量。INSERT语句将整个记录变量插入emp1表,如果插入成功(SQL%FOUND为真),则提交事务,否则回滚撤销事务。试修改雇员编号为7902,重新执行以上程序。 【训练2】 输出雇员工资,雇员工资用不同高度的*表示。 输入并执行以下程序: Sql代码
1. SET SERVEROUTPUT ON 2. BEGIN
3. FOR re IN (SELECT ename,sal FROM EMP) LOOP
4. DBMS_OUTPUT.PUT_LINE(rpad(re.ename,12,' ')||rpad('*',re.sal/100,'*'));
5. END LOOP; 6. END;
输出结果为: Sql代码
1. SMITH ********
2. ALLEN **************** 3. WARD *************
4. JONES ****************************** 5. MARTIN *************
6. BLAKE *****************************
7. CLARK *****************************
8. SCOTT ******************************
9. KING ************************************************** 10. TURNER *************** 11. ADAMS *********** 12. JAMES **********
13. FORD ****************************** 14. MILLER ************* 15. 执行结果为:
16. PL/SQL 过程已成功完成。
说明:第一个rpad函数产生对齐效果,第二个rpad函数根据工资额产生不同数目的*。该程序采用了隐式的简略游标循环形式。
【训练3】 编写程序,格式化输出部门信息。 输入并执行如下程序: Sql代码:
1. SET SERVEROUTPUT ON
2. DECLARE 3. 4. 5. 6.
v_count number:=0;
CURSOR dept_cursor IS SELECT * FROM dept; BEGIN
DBMS_OUTPUT.PUT_LINE('部门列表');
7. DBMS_OUTPUT.PUT_LINE('---------------------------------'); 8. FOR Dept_record IN dept_cursor LOOP
9. DBMS_OUTPUT.PUT_LINE('部门编号:'|| Dept_record.deptno); 10. DBMS_OUTPUT.PUT_LINE('部门名称:'|| Dept_record.dname); 11. DBMS_OUTPUT.PUT_LINE('所在城市:'|| Dept_record.loc); 12. DBMS_OUTPUT.PUT_LINE('---------------------------------'); 13. v_count:= v_count+1;
14. END LOOP;
15. DBMS_OUTPUT.PUT_LINE('共有'||to_char(v_count)||'个部门!'); 16. END;
输出结果为: Sql代码
1. 部门列表
2. ------------------------------------ 3. 部门编号:10
4. 部门名称:ACCOUNTING 5. 所在城市:NEW YORK 6. 7. 8. 9.
------------------------------------ 部门编号:20
部门名称:RESEARCH 所在城市:DALLAS
10. ...
11. 共有4个部门!
12. PL/SQL 过程已成功完成。
说明:该程序中将字段内容垂直排列。V_count变量记录循环次数,即部门个数。 【训练4】 已知每个部门有一个经理,编写程序,统计输出部门名称、部门总人数、总工资和部门经理。
输入并执行如下程序: Sql代码
1. SET SERVEROUTPUT ON 2. DECLARE
3. v_deptno number(8); 4. v_count number(3); 5. v_sumsal number(6);