源码PL/SQL从入门到精通第十三章子程序Part1
对于PL/SQL这种基本上面向过程的语言来讲,子程序(过程和函数)就是其核心所在了。
整个解决方案可通过组织、调用由过程和函数构成的模块来实现。
在“Divide and conquer”(分而治之)的编程世界中,子程序就是程序员手中的兵器,用的越熟练越好。
--代码 13.1 创建过程示例 CREATE OR REPLACE PROCEDURE newdept ( p_deptno dept.deptno%TYPE, --部门编号 p_dname dept.dname%TYPE, --部门名称 p_loc dept.loc%TYPE --位置 ) AS v_deptcount NUMBER; --保存是否存在员工编号 BEGIN SELECT COUNT (*) INTO v_deptcount FROM dept WHERE deptno = p_deptno; --查询在dept表中是否存在部门编号 IF v_deptcount > 0 --如果存在相同的员工记录 THEN --抛出异常 raise_application_error (-20002, '出现了相同的部门记录'); END IF; INSERT INTO dept(deptno, dname, loc) VALUES (p_deptno, p_dname, p_loc);--插入记录 COMMIT; --提交事务 END; SELECT * FROM dept; --代码13.2 调用过程示例 BEGIN newdept(10,'成本科','深圳'); EXCEPTION WHEN OTHERS THEN DBMS_OUTPUT.put_line('产生了错误:'||SQLERRM); END; --查询Oracle中命名块的列表 SELECT object_type 对象类型, object_name 对象名称, status 状态 FROM user_objects WHERE object_type IN ('PACKAGE', 'PACKAGE BODY', 'FUNCTION', 'PROCEDURE') ORDER BY object_type, status, object_name; --代码13.3 创建NewDept过程 CREATE OR REPLACE PROCEDURE newdept ( p_deptno IN NUMBER, --部门编号 p_dname IN VARCHAR2, --部门名称 p_loc IN VARCHAR2 --位置 ) AS v_deptcount NUMBER(4); --保存是否存在员工编号 e_duplication_dept EXCEPTION; BEGIN SELECT COUNT (*) INTO v_deptcount FROM dept WHERE deptno = p_deptno; --查询在dept表中是否存在部门编号 IF v_deptcount > 0 --如果存在相同的员工记录 THEN --抛出异常 RAISE e_duplication_dept; END IF; INSERT INTO dept(deptno, dname, loc) VALUES (p_deptno, p_dname, p_loc);--插入记录 COMMIT; --提交事务 EXCEPTION WHEN e_duplication_dept THEN ROLLBACK; raise_application_error (-20002, '出现了相同的员工记录'); END; SHOW ERRORS; SELECT * FROM emp; --代码 13.4 Getraisedsalary函数示例 CREATE OR REPLACE FUNCTION getraisedsalary (p_empno emp.empno%TYPE) RETURN NUMBER IS v_job emp.job%TYPE; --职位变量 v_sal emp.sal%TYPE; --薪资变量 v_salaryratio NUMBER (10, 2); --调薪比率 BEGIN --获取员工表中的薪资信息 SELECT job, sal INTO v_job, v_sal FROM emp WHERE empno = p_empno; CASE v_job --根据不同的职位获取调薪比率 WHEN '职员' THEN v_salaryratio := 1.09; WHEN '销售人员' THEN v_salaryratio := 1.11; WHEN '经理' THEN v_salaryratio := 1.18; ELSE v_salaryratio := 1.05; END CASE; IF v_salaryratio <> 1 --如果有调薪的可能 THEN RETURN ROUND(v_sal * v_salaryratio,2); --返回调薪后的薪资 ELSE RETURN v_sal; --否则不返回薪资 END IF; EXCEPTION WHEN NO_DATA_FOUND THEN RETURN 0; --如果没找到原工记录,返回0 END; --代码13.5 函数调用示例 DECLARE v_raisedsal NUMBER(10,2); --定义保存调薪记录的临时文件 BEGIN --调用函数获取调薪后的记录 DBMS_OUTPUT.PUT_LINE('7369员工调薪记录:'||getraisedsalary(7369)); v_raisedsal:=getraisedsalary(7521); DBMS_OUTPUT.PUT_LINE('7521员工调薪记录:'||getraisedsalary(7521)); END; SELECT * FROM emp; --代码13.6 在过程中使用Return语句 CREATE OR REPLACE PROCEDURE RaiseSalary( p_empno emp.empno%TYPE --员工编号参数 ) AS v_job emp.job%TYPE; --局部的职位变量 v_sal emp.sal%TYPE; --局部的薪资变量 BEGIN --查询员工信息 SELECT job,sal INTO v_job,v_sal FROM emp WHERE empno=p_empno; IF v_job<>'职员' THEN --仅为职员加薪 RETURN; --如果不是职员,则退出 ELSIF v_sal>3000 THEN --如果职员薪资大于3000,则退出 RETURN; ELSE --否则更新薪资记录 UPDATE emp set sal=ROUND(sal*1.12,2) WHERE empno=p_empno; END IF; EXCEPTION WHEN NO_DATA_FOUND THEN --异常处理 DBMS_OUTPUT.PUT_LINE('没有找到员工记录'); END; --查看过程和函数列表 SELECT object_name, created, last_ddl_time, status FROM user_objects WHERE object_type IN ('FUNCTION','PROCEDURE'); --查看过程的源代码 SELECT line, text FROM user_source WHERE NAME = 'RAISESALARY' ORDER BY line; --查看过程的编译错误 SELECT line, POSITION, text FROM user_errors WHERE NAME = 'RAISESALARY' ORDER BY SEQUENCE; --删除子程序(函数或过程) DROP FUNCTION getraisedsalary ; DROP PROCEDURE NewDept; SELECT * FROM dept; --代码13.7 Insert过程示例 CREATE OR REPLACE PROCEDURE insertdept( p_deptno NUMBER, --定义形式参数 p_dname VARCHAR2, p_loc VARCHAR2 ) AS v_count NUMBER(10); BEGIN SELECT COUNT(deptno) INTO v_count FROM dept WHERE deptno=p_deptno; IF v_count>1 THEN RAISE_APPLICATION_ERROR(-20001,'数据库中存在相同名称的部门编号!'); END IF; INSERT INTO dept VALUES(p_deptno,p_dname,p_loc); --在过程体中使用形式参数 COMMIT; END; --实参和形参必须类型兼容,否则报错 BEGIN insertdept('ABC','行政部','德克萨斯'); EXCEPTION WHEN OTHERS THEN DBMS_OUTPUT.put_line(SQLCODE||' '||SQLERRM); END; --代码13.8 使用In模式 CREATE OR REPLACE PROCEDURE insertdept( p_deptno IN NUMBER:=55, --定义形式参数,并赋初值 p_dname IN VARCHAR2, p_loc IN VARCHAR2 ) AS v_count NUMBER(10); BEGIN --p_dname:='市场策略部'; --错误,不能对IN模式参数进行赋值 SELECT COUNT(deptno) INTO v_count FROM dept WHERE deptno=p_deptno; IF v_count>1 THEN RAISE_APPLICATION_ERROR(-20001,'数据库中存在相同名称的部门编号!'); END IF; INSERT INTO dept VALUES(p_deptno,p_dname,p_loc); --在过程体中使用形式参数 COMMIT; END; --以下过程的编译错误查询不到 SELECT line, POSITION, text FROM user_errors WHERE NAME = 'insertdept' ORDER BY SEQUENCE; --调用过程时传递的参数称为实参 BEGIN insertdept(55,'勤运部','西北'); END; select * from dept; --代码 13.9 使用out模式 CREATE OR REPLACE PROCEDURE OutRaiseSalary( p_empno IN NUMBER, p_raisedSalary OUT NUMBER --定义一个员工加薪后的薪资的输出变量 ) AS v_sal NUMBER(10,2); --定义本地局部变量 v_job VARCHAR2(10); BEGIN p_raisedSalary:=0; --变量赋初值 SELECT sal,job INTO v_sal,v_job FROM emp WHERE empno=p_empno; --查询员工信息 IF v_job='职员' THEN --仅对职员加薪 p_raisedSalary:=v_sal*1.12; --对OUT模式的参数进行赋值是合法的 UPDATE emp SET sal=p_raisedSalary WHERE empno=p_empno; ELSE p_raisedSalary:=v_sal*1.1; --否则赋原来的薪资值 UPDATE emp SET sal=p_raisedSalary WHERE empno=p_empno; END IF; EXCEPTION WHEN NO_DATA_FOUND THEN --异常处理语句块 DBMS_OUTPUT.put_line('没有找到该员工的记录'); END; SELECT * FROM emp; DECLARE v_raisedsalary NUMBER(10,2); --定义一个变量保存输出值 BEGIN v_raisedsalary:=100; --这个赋值在传入到OutRaiseSalary后会被忽略 OutRaiseSalary(5093,v_raisedsalary); --调用函数 DBMS_OUTPUT.put_line(v_raisedsalary); --显示输出参数的值 END; --代码13.10 使用In Out模式 CREATE OR REPLACE PROCEDURE calcRaisedSalary( p_job IN VARCHAR2, p_salary IN OUT NUMBER --定义输入输出参数 ) AS v_sal NUMBER(10,2); --保存调整后的薪资值 BEGIN if p_job='职员' THEN --根据不同的job进行薪资的调整 v_sal:=p_salary*1.12; ELSIF p_job='销售人员' THEN v_sal:=p_salary*1.18; ELSIF p_job='经理' THEN v_sal:=p_salary*1.19; ELSE v_sal:=p_salary*1.1; END IF; p_salary:=v_sal; --将调整后的结果赋给输入输出参数 END calcRaisedSalary;??
相关热词:
本站内容来源于网络,如有侵权请与我们联系,我们会及时删除,我们深感抱歉!
注:本站所有信息仅供用于网络技术学习参考,学习中请遵循相关法律法规!
本文地址: https://v30.fanwenzhu.com/jiaob/net/10164.shtml
相关文章
热门TAG
win10 ecshop 主机 阿里云 解决 配置 C# C++ 解析 SQL语句 命令 Go语言 方法 CSS3 HTML5 CSS win7 MSSQL 服务器配置 IIS7.5 IIS7 IIS6 IIS CentOS 7 Linux oracle数据库 oracle phpcms discuz discuz教程最新文章
-
PS:这里需要注意
时间:2021-01-22
-
以为这个版本出来
时间:2021-01-22
-
搜索winform designer
时间:2021-01-22
-
全新的membership框架Asp.ne
时间:2021-01-21
-
i dont know;18if (msg.Contains(
时间:2021-01-21
-
统筹管理路由规则.
时间:2021-01-21
-
根据switch-case语句来逐一判
时间:2021-01-21
-
EntityFramework 5.0 CodeFirst 教
时间:2021-01-21
热门文章
-
.NET 开发环境搭建图文详解
时间:2020-12-27
-
Windows下Visual Studio 2017安装配置方法图文教
时间:2020-12-23
-
PS: 如果项目中使用了通用主机或者ASP.
时间:2021-01-12
-
.Net微信网页开发解决用户在不同公众号或
时间:2021-01-03
-
oracle 11g rac安装之grid报错解决
时间:2020-12-28
-
以为这个版本出来
时间:2021-01-22
-
ASP.NET Core 3.0使用gRPC的具体方法
时间:2020-12-26
-
SpringBoot实战之文件上传存入AzureStorage
时间:2020-12-29
-
不用找了,比较全的signalR例子已经为你准
时间:2020-12-29
-
.NET Core3.1编写混合C++程序
时间:2020-12-26
