PL/SQL-->包的创建与管理
2014-11-25 18:10
288 查看
PL/SQL-->包的创建与管理
包,是一个逻辑集合,是PL/SQL类型、PL/SQL项以及PL/SQL子程序的集合。PL/SQL类型包括table类型,record类型。PL/SQL项则包括游标,游标变量。PL/SQL子程序包括过程,函数等。可以说包可谓是包罗万象。包是所有PL/SQL相关资源的汇总。
包的使用可以简化应用程序设计,实现信息掩藏,子程序重载等功能。
包的优点
1.模块化:将函数,子程序全部融合在一起,使得成为一个有机的整体,封装了相关的结构。
2.易于维护:整合了子程序,更易于维护。
3.简化应用程序设计:包的声明与包体内容相分离。
4.隐藏信息:私有对象不可访问,所有的包体内代码可以实现隐藏。
5.节省I/O:一次编译,多次使用。
一、包的组成与创建语法
包头:用于定义包的公共组件,如函数头,过程头,游标以及常量,变量等。包头中定义的公共组件可以在包内引用,也可以被其它子程序引用。
包体:用于定义包头中定义过的过程和函数。包体内可以单独定义私有组件,包括变量,常量,过程和函数等。私有组件只能在包内使用,而不能被其它子程序所调用。
一言以蔽之,包头定义包的声明及描述部分,而包体则定义了对应包的具体执行部分。
创建包的语法:
CREATE [OR REPLACE] PACKAGE
package_name
--定义包头
{AS|IS}
public_variable_declarations |
public_type_declarations |
public_exception_declarations |
public_cursor_declarations |
function_declarations |
procedure_specifications
END [package_name]
CREATE [OR REPLACE] PACKAGE BODY
package_name
--定义包体,包体中的package_name应当与包头中的package_name相同
{AS|IS}
private_variable_declarations |
private_type_declarations |
private_exception_declarations |
private_cursor_declarations |
function_declarations |
procedure_specifications
END [package_name]
二、创建包
下面演示包的创建,基于用户scott创建,存储过程,函数等依赖于其下的对象
1.创建包头
CREATE OR REPLACE PACKAGE emp_package
IS
--创建包头,包的名字为emp_package
g_deptno NUMBER(3) :=
30;
--定义一个公共变量g_deptno
PROCEDURE add_employee(eno NUMBER, name VARCHAR2, salary NUMBER,
dno NUMBER DEFAULT g_deptno); --声明过程
PROCEDURE fire_employee(eno
NUMBER);
--声明过程
FUNCTION get_sal(eno NUMBER) RETURN
NUMBER;
--声明函数
END emp_package;
/
2.创建包体
CREATE OR REPLACE PACKAGE BODY emp_package
IS
--创建包体,注意,包体中包的名字必须与包头的名字相一致
FUNCTION validate_deptno(v_deptno NUMBER) RETURN
BOOLEAN --创建一个私有函数,注:此私有函数不能被该包外子程序调用
IS
v_temp INT;
BEGIN
SELECT 1 INTO v_temp FROM dept WHERE deptno = v_deptno;
RETURN TRUE;
EXCEPTION
WHEN NO_DATA_FOUND THEN
RETURN FALSE;
END;
PROCEDURE add_employee
--创建添加雇员的过程
(eno NUMBER, name VARCHAR2, salary NUMBER, dno NUMBER DEFAULT
g_deptno) IS
BEGIN
IF validate_deptno(dno) THEN
--该过程调用了包内的一个函数validate_deptno来验证dno的有效性
INSERT INTO emp(empno, ename, sal, deptno) VALUES(eno, name,
salary, dno);
ELSE
RAISE_APPLICATION_ERROR(-20000, '不存在该部门');
END IF;
EXCEPTION
WHEN DUP_VAL_ON_INDEX THEN
RAISE_APPLICATION_ERROR(-20011, '该雇员已存在');
END;
PROCEDURE fire_employee(eno NUMBER) IS
--创建解除雇员的过程
BEGIN
DELETE FROM emp WHERE empno = eno;
IF SQL%NOTFOUND THEN
RAISE_APPLICATION_ERROR(-20012, '该雇员不存在');
END IF;
END;
FUNCTION get_sal(eno NUMBER) RETURN NUMBER IS
--创建函数get_sal返回雇员的薪水
v_sal emp.sal%TYPE;
BEGIN
SELECT sal INTO v_sal FROM emp WHERE empno = eno;
RETURN v_sal;
EXCEPTION
WHEN NO_DATA_FOUND THEN
RAISE_APPLICATION_ERROR(-20012, '该雇员不存在');
END;
END emp_package;
/
3.创建仅包含包头的包(仅包含包头的包也可以被调用,具体参照后面的包的调用)
CREATE OR REPLACE PACKAGE global_int
IS
g_positive CONSTANT NUMBER:=10;
g_negative CONSTANT NUMBER:=-10;
END global_int;
三、包的调用
包的私有对象只能在包内调用。如上面的例子中对包内私有函数validate_deptno进行了直接调用
包的公共对象,既可以在包内调用,也可以由其他应用程序调用。使用其他应用程序调用时的方法:包名.包对象
1.调用包的公共变量
scott@ORCL> exec emp_package.g_deptno:=10;
2.调用包的公共过程
scott@ORCL> exec
emp_package.add_employee(2222,'Robinson',3000);
--此调用未指定部门号,则使用缺省值,但前面执行了
--exec
emp_package.g_deptno:=10;故部门号变为10
scott@ORCL> exec
emp_package.add_employee(3333,'Jackson',4000,20);
scott@ORCL> select * from emp where empno
in(2222,3333);
EMPNO
ENAME
JOB
MGR
HIREDATE
SAL
COMM
DEPTNO
---------- ---------- --------- ---------- --------- ----------
---------- ----------
2222
Robinson
3000
10
3333
Jackson
4000
20
3.调用包的公共函数
scott@ORCL> var sal number
scott@ORCL> exec
:sal:=emp_package.get_sal(7788);
PL/SQL procedure successfully completed.
scott@ORCL> print sal
SAL
----------
310
4.以不同用户身份调用包.需要使用schema名字来调用,即:用户名.包名.包对象名
scott@ORCL> conn
lion/lion
--注意帐户需要具有执行所调用包的权限
lion@ORCL> exec
scott.emp_package.fire_employee(2222);
5.调用远程数据库包的公共对象。调用方法:包名.包对象名@数据库链接名
sys@ASMDB> create database link orcl
2 connect to lion identified by lion
3 using 'orcl';
Database link created.
sys@ASMDB> exec
scott.emp_package.add_employee@orcl(4444,'Richard',4000);
BEGIN scott.emp_package.add_employee@orcl(4444,'Richard',4000);
END;
*
ERROR at line 1:
ORA-06550: line 1, column 7:
--注意远程调用时,对于缺省的参数不适用,需要明确指定参数
PLS-00424: RPC defaults cannot include Package State
ORA-06550: line 1, column 7:
PL/SQL: Statement ignored
sys@ASMDB> exec
scott.emp_package.add_employee@orcl(4444,'Richard',4000,20);
--调用被成功执行
PL/SQL procedure successfully completed.
6.无包体包的调用(使用前面创建的包global_int)
scott@ORCL> BEGIN
2 DBMS_OUTPUT.PUT_LINE('Result is :
'||2*global_int.g_positive); --使用包DBMS_OUTPUT来调用
3 END;
4 /
Result is : 20
PL/SQL procedure successfully
completed.
scott@ORCL> CREATE OR REPLACE FUNCTION f_negative(m
number) --将包嵌入到函数之中
2 RETURN NUMBER
3 IS
4 BEGIN
5
RETURN(m*global_int.g_negative);
6 END f_negative;
7 /
Function created.
scott@ORCL> EXEC
DBMS_OUTPUT.PUT_LINE(f_negative(2));
-20
PL/SQL procedure successfully completed.
四、包的管理
1.查看包
scott@ORCL> select line,text from
user_source
--查看包头
2 where name='EMP_PACKAGE' and
type='PACKAGE';
LINE TEXT
----------
------------------------------------------------------------
1 PACKAGE emp_package IS
2 g_deptno NUMBER(3) :=
30;
3 PROCEDURE add_employee(eno
NUMBER, name VARCHAR2, salary NUMBER, dno NUMBER DEFAULT
g_deptno);
4 PROCEDURE fire_employee(eno
NUMBER);
5 FUNCTION get_sal(eno NUMBER)
RETURN NUMBER;
6 END emp_package;
scott@ORCL> select line,text from
user_source
--查看包体
2 where name='EMP_PACKAGE' and type='PACKAGE
BODY';
LINE TEXT
----------
--------------------------------------------------------------------------------
1 PACKAGE BODY emp_package IS
2 FUNCTION
validate_deptno(v_deptno NUMBER) RETURN BOOLEAN IS
3
v_temp INT;
4 BEGIN
5
SELECT 1 INTO v_temp FROM dept WHERE deptno = v_deptno;
6
RETURN TRUE;
......................
2.查看包的参数
scott@ORCL> desc emp_package;
PROCEDURE ADD_EMPLOYEE
Argument
Name
Type
In/Out Default?
------------------------------ ----------------------- ------
--------
ENO
NUMBER
IN
NAME
VARCHAR2
IN
SALARY
NUMBER
IN
DNO
NUMBER
IN
DEFAULT
PROCEDURE FIRE_EMPLOYEE
Argument
Name
Type
In/Out Default?
------------------------------ ----------------------- ------
--------
ENO
NUMBER
IN
FUNCTION GET_SAL RETURNS NUMBER
Argument
Name
Type
In/Out Default?
------------------------------ ----------------------- ------
--------
ENO
NUMBER
IN
3.包的删除
DROP PACKAGE package_name
--同时删除包体和包头
scott@ORCL> DROP PACKAGE global_int;
删除包体,保留包头
DROP PACKAGE BODY package_name
--删除包体
scott@ORCL> drop package body emp_package;
Package body dropped.
4.包的编译
重新编译包规范和包体:alter package...compile
重新编译包规范:alter package...compile specification
重新编译包体:alter package...compile body
五、总结
创键包体之前应该先创建包头
包头应当仅仅包含那些希望作为公共对象的部分
包头的声明应包含尽可能少的结构信息
任意包头的变更,需要重新编译该包内的子程序
在包头内定义的任意公共对象可以被任意内部或外部子程序调用
包体内的私有对象仅仅能被该包体内的子程序调用
转自:http://blog.csdn.net/robinson_0612/article/details/6084475
包,是一个逻辑集合,是PL/SQL类型、PL/SQL项以及PL/SQL子程序的集合。PL/SQL类型包括table类型,record类型。PL/SQL项则包括游标,游标变量。PL/SQL子程序包括过程,函数等。可以说包可谓是包罗万象。包是所有PL/SQL相关资源的汇总。
包的使用可以简化应用程序设计,实现信息掩藏,子程序重载等功能。
包的优点
1.模块化:将函数,子程序全部融合在一起,使得成为一个有机的整体,封装了相关的结构。
2.易于维护:整合了子程序,更易于维护。
3.简化应用程序设计:包的声明与包体内容相分离。
4.隐藏信息:私有对象不可访问,所有的包体内代码可以实现隐藏。
5.节省I/O:一次编译,多次使用。
一、包的组成与创建语法
包头:用于定义包的公共组件,如函数头,过程头,游标以及常量,变量等。包头中定义的公共组件可以在包内引用,也可以被其它子程序引用。
包体:用于定义包头中定义过的过程和函数。包体内可以单独定义私有组件,包括变量,常量,过程和函数等。私有组件只能在包内使用,而不能被其它子程序所调用。
一言以蔽之,包头定义包的声明及描述部分,而包体则定义了对应包的具体执行部分。
创建包的语法:
CREATE [OR REPLACE] PACKAGE
package_name
--定义包头
{AS|IS}
public_variable_declarations |
public_type_declarations |
public_exception_declarations |
public_cursor_declarations |
function_declarations |
procedure_specifications
END [package_name]
CREATE [OR REPLACE] PACKAGE BODY
package_name
--定义包体,包体中的package_name应当与包头中的package_name相同
{AS|IS}
private_variable_declarations |
private_type_declarations |
private_exception_declarations |
private_cursor_declarations |
function_declarations |
procedure_specifications
END [package_name]
二、创建包
下面演示包的创建,基于用户scott创建,存储过程,函数等依赖于其下的对象
1.创建包头
CREATE OR REPLACE PACKAGE emp_package
IS
--创建包头,包的名字为emp_package
g_deptno NUMBER(3) :=
30;
--定义一个公共变量g_deptno
PROCEDURE add_employee(eno NUMBER, name VARCHAR2, salary NUMBER,
dno NUMBER DEFAULT g_deptno); --声明过程
PROCEDURE fire_employee(eno
NUMBER);
--声明过程
FUNCTION get_sal(eno NUMBER) RETURN
NUMBER;
--声明函数
END emp_package;
/
2.创建包体
CREATE OR REPLACE PACKAGE BODY emp_package
IS
--创建包体,注意,包体中包的名字必须与包头的名字相一致
FUNCTION validate_deptno(v_deptno NUMBER) RETURN
BOOLEAN --创建一个私有函数,注:此私有函数不能被该包外子程序调用
IS
v_temp INT;
BEGIN
SELECT 1 INTO v_temp FROM dept WHERE deptno = v_deptno;
RETURN TRUE;
EXCEPTION
WHEN NO_DATA_FOUND THEN
RETURN FALSE;
END;
PROCEDURE add_employee
--创建添加雇员的过程
(eno NUMBER, name VARCHAR2, salary NUMBER, dno NUMBER DEFAULT
g_deptno) IS
BEGIN
IF validate_deptno(dno) THEN
--该过程调用了包内的一个函数validate_deptno来验证dno的有效性
INSERT INTO emp(empno, ename, sal, deptno) VALUES(eno, name,
salary, dno);
ELSE
RAISE_APPLICATION_ERROR(-20000, '不存在该部门');
END IF;
EXCEPTION
WHEN DUP_VAL_ON_INDEX THEN
RAISE_APPLICATION_ERROR(-20011, '该雇员已存在');
END;
PROCEDURE fire_employee(eno NUMBER) IS
--创建解除雇员的过程
BEGIN
DELETE FROM emp WHERE empno = eno;
IF SQL%NOTFOUND THEN
RAISE_APPLICATION_ERROR(-20012, '该雇员不存在');
END IF;
END;
FUNCTION get_sal(eno NUMBER) RETURN NUMBER IS
--创建函数get_sal返回雇员的薪水
v_sal emp.sal%TYPE;
BEGIN
SELECT sal INTO v_sal FROM emp WHERE empno = eno;
RETURN v_sal;
EXCEPTION
WHEN NO_DATA_FOUND THEN
RAISE_APPLICATION_ERROR(-20012, '该雇员不存在');
END;
END emp_package;
/
3.创建仅包含包头的包(仅包含包头的包也可以被调用,具体参照后面的包的调用)
CREATE OR REPLACE PACKAGE global_int
IS
g_positive CONSTANT NUMBER:=10;
g_negative CONSTANT NUMBER:=-10;
END global_int;
三、包的调用
包的私有对象只能在包内调用。如上面的例子中对包内私有函数validate_deptno进行了直接调用
包的公共对象,既可以在包内调用,也可以由其他应用程序调用。使用其他应用程序调用时的方法:包名.包对象
1.调用包的公共变量
scott@ORCL> exec emp_package.g_deptno:=10;
2.调用包的公共过程
scott@ORCL> exec
emp_package.add_employee(2222,'Robinson',3000);
--此调用未指定部门号,则使用缺省值,但前面执行了
--exec
emp_package.g_deptno:=10;故部门号变为10
scott@ORCL> exec
emp_package.add_employee(3333,'Jackson',4000,20);
scott@ORCL> select * from emp where empno
in(2222,3333);
EMPNO
ENAME
JOB
MGR
HIREDATE
SAL
COMM
DEPTNO
---------- ---------- --------- ---------- --------- ----------
---------- ----------
2222
Robinson
3000
10
3333
Jackson
4000
20
3.调用包的公共函数
scott@ORCL> var sal number
scott@ORCL> exec
:sal:=emp_package.get_sal(7788);
PL/SQL procedure successfully completed.
scott@ORCL> print sal
SAL
----------
310
4.以不同用户身份调用包.需要使用schema名字来调用,即:用户名.包名.包对象名
scott@ORCL> conn
lion/lion
--注意帐户需要具有执行所调用包的权限
lion@ORCL> exec
scott.emp_package.fire_employee(2222);
5.调用远程数据库包的公共对象。调用方法:包名.包对象名@数据库链接名
sys@ASMDB> create database link orcl
2 connect to lion identified by lion
3 using 'orcl';
Database link created.
sys@ASMDB> exec
scott.emp_package.add_employee@orcl(4444,'Richard',4000);
BEGIN scott.emp_package.add_employee@orcl(4444,'Richard',4000);
END;
*
ERROR at line 1:
ORA-06550: line 1, column 7:
--注意远程调用时,对于缺省的参数不适用,需要明确指定参数
PLS-00424: RPC defaults cannot include Package State
ORA-06550: line 1, column 7:
PL/SQL: Statement ignored
sys@ASMDB> exec
scott.emp_package.add_employee@orcl(4444,'Richard',4000,20);
--调用被成功执行
PL/SQL procedure successfully completed.
6.无包体包的调用(使用前面创建的包global_int)
scott@ORCL> BEGIN
2 DBMS_OUTPUT.PUT_LINE('Result is :
'||2*global_int.g_positive); --使用包DBMS_OUTPUT来调用
3 END;
4 /
Result is : 20
PL/SQL procedure successfully
completed.
scott@ORCL> CREATE OR REPLACE FUNCTION f_negative(m
number) --将包嵌入到函数之中
2 RETURN NUMBER
3 IS
4 BEGIN
5
RETURN(m*global_int.g_negative);
6 END f_negative;
7 /
Function created.
scott@ORCL> EXEC
DBMS_OUTPUT.PUT_LINE(f_negative(2));
-20
PL/SQL procedure successfully completed.
四、包的管理
1.查看包
scott@ORCL> select line,text from
user_source
--查看包头
2 where name='EMP_PACKAGE' and
type='PACKAGE';
LINE TEXT
----------
------------------------------------------------------------
1 PACKAGE emp_package IS
2 g_deptno NUMBER(3) :=
30;
3 PROCEDURE add_employee(eno
NUMBER, name VARCHAR2, salary NUMBER, dno NUMBER DEFAULT
g_deptno);
4 PROCEDURE fire_employee(eno
NUMBER);
5 FUNCTION get_sal(eno NUMBER)
RETURN NUMBER;
6 END emp_package;
scott@ORCL> select line,text from
user_source
--查看包体
2 where name='EMP_PACKAGE' and type='PACKAGE
BODY';
LINE TEXT
----------
--------------------------------------------------------------------------------
1 PACKAGE BODY emp_package IS
2 FUNCTION
validate_deptno(v_deptno NUMBER) RETURN BOOLEAN IS
3
v_temp INT;
4 BEGIN
5
SELECT 1 INTO v_temp FROM dept WHERE deptno = v_deptno;
6
RETURN TRUE;
......................
2.查看包的参数
scott@ORCL> desc emp_package;
PROCEDURE ADD_EMPLOYEE
Argument
Name
Type
In/Out Default?
------------------------------ ----------------------- ------
--------
ENO
NUMBER
IN
NAME
VARCHAR2
IN
SALARY
NUMBER
IN
DNO
NUMBER
IN
DEFAULT
PROCEDURE FIRE_EMPLOYEE
Argument
Name
Type
In/Out Default?
------------------------------ ----------------------- ------
--------
ENO
NUMBER
IN
FUNCTION GET_SAL RETURNS NUMBER
Argument
Name
Type
In/Out Default?
------------------------------ ----------------------- ------
--------
ENO
NUMBER
IN
3.包的删除
DROP PACKAGE package_name
--同时删除包体和包头
scott@ORCL> DROP PACKAGE global_int;
删除包体,保留包头
DROP PACKAGE BODY package_name
--删除包体
scott@ORCL> drop package body emp_package;
Package body dropped.
4.包的编译
重新编译包规范和包体:alter package...compile
重新编译包规范:alter package...compile specification
重新编译包体:alter package...compile body
五、总结
创键包体之前应该先创建包头
包头应当仅仅包含那些希望作为公共对象的部分
包头的声明应包含尽可能少的结构信息
任意包头的变更,需要重新编译该包内的子程序
在包头内定义的任意公共对象可以被任意内部或外部子程序调用
包体内的私有对象仅仅能被该包体内的子程序调用
转自:http://blog.csdn.net/robinson_0612/article/details/6084475
相关文章推荐
- PL/SQL --> 包的创建与管理
- SQL 基础-->创建和管理表
- PL/SQL --> 包的创建与管理
- <一>Oracle11g的安装+数据库创建+PL/SQL Dev的使用初步
- PL/SQL --> 包的创建与管理
- PL/SQL --> 包的创建与管理
- PL/SQL --> 包的创建与管理
- PL/SQL--&gt;隐式游标(SQL%FOUND)
- PL/SQL dev工具 使用for update-->Edit Date 时出错"These query results are not updateable,Include the ROWID to get updateable results."
- PL/SQL--&gt;游标
- PL/SQL--&gt;包重载、初始化
- PL/SQL--&gt;DBMS_DDL包的使用
- PL/SQL--&gt;INSTEAD&nbsp;OF&nbsp;触发器
- SQL扩展语言T-SQL和PL-SQL<转>
- SQL 基础-->创建和管理表
- Oracle - SQL 优化 -------- > 创建计划表
- <转载>PL/SQL Developer如何连接64位的Oracle图解
- .NET调用osql.exe执行sql脚本创建表和存储过程<转> 代码
- 关于pl/sql 操作符=&amp;gt;
- PL/SQL 语言,用户管理 programming & Operations(1)