源码-PL/SQL从入门到精通-第二章-PL/SQL基本概念-Part 二
源码-PL/SQL从入门到精通-第二章-PL/SQL基本概念-Part 2
随书光盘中的源码没有序号,部分找不到或者有bug,调试过程中一并更正。
其中,还有两个彩蛋:“双十九”乘法口诀表和“双九九”加法口诀表的输出(PL/SQL实现),以及一个附加(加薪函数的调用)
代码如下:
--代码2.9 使用嵌套块更新和插入部门表 /*说明: 1.随书源代码中v_deptno前缺少&符号,导致异常处理模块报错“ORA-01400: 无法将 NULL 插入”。 本人调试了半天,才发现问题所在,现已修复。 2.此段代码为手工录入,因为在随书光盘中未找到*/ /*以下为调试过程中使用的sql语句: create table dept2 as select * from dept; select * from dept2; drop table dept2;*/ DECLARE v_deptno NUMBER(2); v_deptname VARCHAR2(14); BEGIN --内部嵌套块 BEGIN SELECT dname INTO v_deptname FROM dept2 WHERE deptno = &v_deptno; DBMS_OUTPUT.PUT_LINE('您查询的部门名称为:' || v_deptname); END; --内部嵌套块 DECLARE v_loc VARCHAR2(13) := '上海浦东'; BEGIN UPDATE dept2 SET loc = v_loc WHERE deptno = v_deptno; DBMS_OUTPUT.PUT_LINE('在内部嵌套块中成功更新部门资料'); COMMIT; END; EXCEPTION WHEN NO_DATA_FOUND THEN BEGIN INSERT INTO dept2 VALUES (&v_deptno,'IT开发','全球'); DBMS_OUTPUT.PUT_LINE('在异常处理嵌套块成功新增部门资料'); COMMIT; EXCEPTION WHEN OTHERS THEN DBMS_OUTPUT.PUT_LINE(SQLERRM); END; END; --代码2.10 命名嵌套块(在代码2.9中增加了<<查询与员工名称块>>等三个标签) DECLARE v_deptno NUMBER(2); v_deptname VARCHAR2(14); BEGIN --内部嵌套块 <<查询员工名称块>> BEGIN SELECT dname INTO v_deptname FROM dept2 WHERE deptno = &v_deptno; DBMS_OUTPUT.PUT_LINE('您查询的部门名称为:' || v_deptname); END; --内部嵌套块 <<更新员工记录块>> DECLARE v_loc VARCHAR2(13) := '上海浦东'; BEGIN UPDATE dept2 SET loc = v_loc WHERE deptno = v_deptno; DBMS_OUTPUT.PUT_LINE('在内部嵌套块中成功更新部门资料'); COMMIT; END; EXCEPTION WHEN NO_DATA_FOUND THEN <<插入员工记录块>> BEGIN INSERT INTO dept2 VALUES (&v_deptno,'IT开发','全球'); DBMS_OUTPUT.PUT_LINE('在异常处理嵌套块成功新增部门资料'); COMMIT; EXCEPTION WHEN OTHERS THEN DBMS_OUTPUT.PUT_LINE(SQLERRM); END; END; --代码2.11 PL/SQL变量定义示例 DECLARE v_DeptName VARCHAR2(10); --定义标量变量 v_LoopCounter BINARY_INTEGER; --使用PL/SQL类型定义标量变量 --定义记录类型 TYPE t_Employee IS RECORD (EmpName VARCHAR2(20),EmpNo NUMBER(7),Job VARCHAR2(20)); v_Employee t_Employee; --定义记录类型变量 TYPE csor IS REF CURSOR; --定义游标变量 v_date DATE NOT NULL DEFAULT SYSDATE;--定义变量并指定默认值 BEGIN NULL; END; / --代码2.12 使用CASE进行条件判断 CREATE OR REPLACE FUNCTION GetAddSalaryRatioCASE(p_Job VARCHAR2) RETURN NUMBER AS v_Result NUMBER(7,2); BEGIN CASE p_Job --使用CASE WHEN语句进行条件判断 WHEN 'CLERK' THEN --职员 v_Result:=0.10; WHEN 'SALESMAN' THEN --销售 v_Result:=0.12; WHEN 'MANAGER' THEN --经理 v_Result:=0.15; WHEN 'cont' THEN --consultant,翻倍 v_Result:=1; END CASE; RETURN v_Result; --返回值 END; --代码2.13 使用FOR循环打印九九乘法口诀表 DECLARE v_Number1 NUMBER(3); --外层循环变量 v_Number2 NUMBER(3); --内存循环变量 BEGIN FOR v_Number1 IN 1..9 --开始外层循环 LOOP --进行内存循环 FOR v_Number2 IN 1..v_Number1 LOOP --打印口决内容 DBMS_OUTPUT.PUT(v_Number1||'*'||v_Number2||'='||v_Number1*v_Number2||' '); END LOOP; --输出换行 DBMS_OUTPUT.PUT_LINE(''); END LOOP; END; --彩蛋1 使用FOR循环打印“双十九”乘法口诀表(印度乘法口诀表) DECLARE v_Number1 NUMBER(3); --外层循环变量 v_Number2 NUMBER(3); --内存循环变量 BEGIN FOR v_Number1 IN 1..19 --开始外层循环 LOOP --进行内存循环 FOR v_Number2 IN 1..v_Number1 LOOP --打印口决内容 --第十行缩进,使得输出更美观 DBMS_OUTPUT.PUT (v_Number1||'*'||v_Number2||'='||v_Number1*v_Number2||' '); END LOOP; --输出换行 DBMS_OUTPUT.PUT_LINE(''); END LOOP; END; --彩蛋2 使用FOR循环打印“双九九”加法口诀表 DECLARE v_Number1 NUMBER(3); --外层循环变量 v_Number2 NUMBER(3); --内存循环变量 BEGIN FOR v_Number1 IN 1..19 --开始外层循环 LOOP --进行内存循环 FOR v_Number2 IN 1..v_Number1 LOOP --打印口决内容 --第十行缩进,使得输出更美观 DBMS_OUTPUT.PUT (v_Number1||'+'||v_Number2||'='||(v_Number1+v_Number2)||' '); END LOOP; --输出换行 DBMS_OUTPUT.PUT_LINE(''); END LOOP; END; --创建为员工加薪的过程 CREATE OR REPLACE PROCEDURE AddEmpSalary(p_Ratio NUMBER,p_EmpNo NUMBER) AS BEGIN IF p_Ratio>0 THEN --判断传入的参数是否大于0 --如果大于0,则更新Emp表中的数据 UPDATE scott.emp3 SET sal2=sal2*(1+p_Ratio) WHERE EMPNO=p_EmpNo; END IF; --提示加薪成功。 DBMS_OUTPUT.PUT_LINE('加薪成功!'); END; --附加:调用加薪函数 DECLARE v_empno NUMBER(4); v_sal2 VARCHAR2(14); v_ratio VARCHAR2(14); BEGIN SELECT sal2 INTO v_sal2 FROM emp3 WHERE empno = &v_empno; addempsalary(&v_ratio, &v_empno); DBMS_OUTPUT.PUT_LINE('员工'||&v_empno||'已成功加薪百分之'||&v_ratio*100); commit; EXCEPTION WHEN NO_DATA_FOUND THEN BEGIN DBMS_OUTPUT.PUT_LINE('未找到该员工!'); EXCEPTION WHEN OTHERS THEN DBMS_OUTPUT.PUT_LINE(SQLERRM); END; END; update emp3 set sal2=5120000 where empno=7509; --代码2.15 员工加薪管理保代码 /*包规范定义,不包括实现代码*/ CREATE OR REPLACE PACKAGE EmpSalary AS --执行实际的加薪动作 PROCEDURE AddEmpSalary(p_Ratio NUMBER,p_EmpNo NUMBER); --使用IF-ELSIF语句得到加薪比率 FUNCTION GetAddSalaryRatio(p_Job VARCHAR2) RETURN NUMBER; --使用CASE语句得到加薪比率 FUNCTION GetAddSalaryRatioCASE(p_Job VARCHAR2) RETURN NUMBER; END EmpSalary; / /*包体定义*/ CREATE OR REPLACE PACKAGE BODY EmpSalary AS PROCEDURE AddEmpSalary(p_Ratio NUMBER,p_EmpNo NUMBER) AS BEGIN IF p_Ratio>0 THEN --判断传入的参数是否大于0 --如果大于0,则更新Emp表中的数据 UPDATE scott.emp SET sal=sal*(1+p_Ratio) WHERE EMPNO=p_EmpNo; END IF; --提示加薪成功。 DBMS_OUTPUT.PUT_LINE('加薪成功!'); END; FUNCTION GetAddSalaryRatio(p_Job VARCHAR2) RETURN NUMBER AS v_Result NUMBER(7,2); BEGIN IF p_Job='CLERK' THEN --如果为职员,加薪10% v_Result:=0.10; ELSIF p_Job='SALESMAN' THEN --如果为销售职员,加薪12% v_Result:=0.12; ELSIF p_Job='MANAGER' THEN --如果为经理,加薪15% v_Result:=0.15; END IF; RETURN v_Result; END; FUNCTION GetAddSalaryRatioCASE(p_Job VARCHAR2) RETURN NUMBER AS v_Result NUMBER(7,2); BEGIN CASE p_Job --使用CASE WHEN语句进行条件判断 WHEN 'CLERK' THEN --职员 v_Result:=0.10; WHEN 'SALESMAN' THEN --销售 v_Result:=0.12; WHEN 'MANAGER' THEN --经理 v_Result:=0.15; END CASE; RETURN v_Result; --返回值 END; END EmpSalary;