语法
CREATE OR REPLACE PACKAGE package_name
IS|AS
[PRAGMA SERIALLY_RESUABLE]
type_definition|variable_declaration|
exception_declaration|cursor_declaration|
procedure_ declaration|function_ declaration
END [package_name];
注意:元素声明的顺序可以是任意的,但必须先声明后使用;所有元素是可选的;过程和函数的声明只包括原型,不包括具体实现。
创建一个软件包,包括2个变量、2个过程和1个异常。
•语法
CREATE OR REPLACE PACKAGE BODY package_name
IS|AS
[PRAGMA SERIALLY_RESUABLE]
type_definition|variable_declaration|
exception_declaration|
cursor_declaration|
procedure_definition |
function_definition
END [package_name];
注意:包体中函数和过程的原型必须与包规范中的声明完全一致;只有在包规范已经创建的条件下,才可以创建包体;如果包规范中不包含任何函数或过程,则可以不创建包体。
CREATE OR REPLACE PACKAGE BODY pkg_emp
AS
PROCEDURE update_sal(p_empno NUMBER, p_sal NUMBER)
AS
BEGIN
SELECT min(sal), max(sal) INTO minsal,maxsal FROM emp;
IF p_sal BETWEEN minsal AND maxsal THEN
UPDATE emp SET sal=p_sal WHERE empno=p_empno;
IF SQL%NOTFOUND THEN
RAISE_APPLICATION_ERROR(-20000,'The employee doesn''t exist');
END IF;
ELSE
RAISE e_beyondbound;
END IF;
EXCEPTION
WHEN e_beyondbound THEN
DBMS_OUTPUT.PUT_LINE('The salary is beyond bound! ');
END update_sal;
PROCEDURE add_employee(p_empno NUMBER,p_sal NUMBER)
AS
BEGIN
SELECT min(sal), max(sal) INTO minsal,maxsal FROM emp;
IF p_sal BETWEEN minsal AND maxsal THEN
INSERT INTO emp(empno,sal) VALUES(p_empno,p_sal);
ELSE
RAISE e_beyondbound;
END IF;
EXCEPTION
WHEN e_beyondbound THEN
DBMS_OUTPUT.PUT_LINE('The salary is beyond bound! ');
END add_employee;
END pkg_emp;
BEGIN
pkg_emp.update_sal(7844,3000);
pkg_emp.add_employee(1357,4000);
END;
在一个包中重载两个过程,分别以部门号和部门名称为参数,查询相应部门员工名、员工号信息。
CREATE OR REPLACE PACKAGE pkg_overload
AS
PROCEDURE show_emp(p_deptno NUMBER);
PROCEDURE show_emp(p_dname VARCHAR2);
END pkg_overload;
CREATE OR REPLACE PACKAGE BODY pkg_overload
AS
PROCEDURE show_emp(p_deptno NUMBER)
AS
BEGIN
FOR v_emp IN (SELECT * FROM emp WHERE deptno=p_deptno) LOOP
DBMS_OUTPUT.PUT_LINE(v_emp.empno||' '|| v_emp.ename);
END LOOP;
END show_emp;
PROCEDURE show_emp(p_dname VARCHAR2)
AS
v_deptno NUMBER;
BEGIN
SELECT deptno INTO v_deptno FROM dept
WHERE dname=p_dname;
FOR v_emp IN (SELECT * FROM emp
WHERE deptno=v_deptno) LOOP
DBMS_OUTPUT.PUT_LINE(v_emp.empno||' '||
v_emp.ename);
END LOOP;
END show_emp;
END pkg_overload;
CREATE OR REPLACE PACKAGE pkg_emp
AS
minsal NUMBER;
maxsal NUMBER;
e_beyondbound EXCEPTION;
PROCEDURE update_sal(
p_empno NUMBER, p_sal NUMBER);
PROCEDURE add_employee(
p_empno NUMBER,p_sal NUMBER);
END pkg_emp;
CREATE OR REPLACE PACKAGE BODY pkg_emp
AS
PROCEDURE update_sal(p_empno NUMBER, p_sal NUMBER)
AS
BEGIN
IF p_sal BETWEEN minsal AND maxsal THEN
UPDATE emp SET sal=p_sal WHERE empno=p_empno;
IF SQL%NOTFOUND THEN
RAISE_APPLICATION_ERROR(-20000,'The employee
doesn''t exist');
END IF;
ELSE
RAISE e_beyondbound;
END IF;
EXCEPTION
WHEN e_beyondbound THEN
DBMS_OUTPUT.PUT_LINE('The salary is beyond bound!');
END update_sal;
PROCEDURE add_employee(p_empno NUMBER,p_sal NUMBER)
AS
BEGIN
IF p_sal BETWEEN minsal AND maxsal THEN
INSERT INTO emp(empno,sal) VALUES(p_empno,p_sal);
ELSE
RAISE e_beyondbound;
END IF;
EXCEPTION
WHEN e_beyondbound THEN
DBMS_OUTPUT.PUT_LINE('The salary is beyond bound!');
END add_employee;
BEGIN
SELECT min(sal), max(sal) INTO minsal,maxsal FROM emp;
END pkg_emp;
包中变量的持续性是指,当用户调用包时,会创建自己的变量副本,在用户的整个会话过程中持续存在,对用户而言是私有的。
为了测试变量的持续性,先创建一个包含一个变量的包和对包中变量进行读、写的两个过程。
CREATE OR REPLACE PACKAGE variable_pkg
IS
pkg_test NUMBER(6,2) :=0;
END variable_pkg;
CREATE OR REPLACE PROCEDURE get_pkg_test
(p_test OUT NUMBER)
IS
BEGIN
p_test := variable_pkg.pkg_test;
END;
CREATE OR REPLACE PROCEDURE set_pkg_test
(p_test IN NUMBER)
IS
BEGIN
variable_pkg.pkg_test := p_test;
END;
以不同的用户(scott,system)分别启动两个SQL*Plus,进行下列操作,可以看出,包中的变量variable_pkg.pkg_test在scott用户和system用户之间是持续的、独立的。
--user scott
SQL>variable g_test NUMBER;
SQL>EXECUTE get_pkg_test(:g_test);
SQL>PRINT g_test
G_TEST
----------
0
SQL>EXECUTE set_pkg_test(10);
SQL>EXECUTE get_pkg_test(:g_test);
SQL>PRINT g_test
G_TEST
----------
10
--user system
SQL>variable g_test NUMBER
SQL>EXECUTE scott.get_pkg_test(:g_test);
SQL>PRINT g_test
G_TEST
----------
0
SQL>EXECUTE scott.set_pkg_test(20);
SQL>EXECUTE scott.get_pkg_test(:g_test);
SQL>PRINT g_test
G_TEST
----------
20
--user scott
SQL>EXECUTE get_pkg_test(:g_test);
SQL>PRINT g_test
G_TEST
----------
10
本人从事软件项目开发20多年,2005年开始从事Java工程师系列课程的教学工作,录制50多门精品视频课程,包含java基础,jspweb开发,SSH,SSM,SpringBoot,SpringCloud,人工智能,在线支付等众多商业项目,每门课程都包含有项目实战,上课PPT,及完整的源代码下载,有兴趣的朋友可以看看我的在线课堂
讲师课堂链接:https://edu.csdn.net/lecturer/893