PL/SQL学习笔记-5

PL/SQL学习笔记-5java

第10章数据库

[@more@]


第10章 使用过程、函数和包
10.1 子程序位置
当用CREATE OR REPLACE建立子程序时,该子程序被存储到数据字典中。除源文本外,子程序以编译形式存储,这叫作p-code(伪码)。
Oracle9i容许你把一个子程序编译成本地操做系统代码,而非伪代码。区别在于执行的时候伪代码任然须要被解释,本地代码不须要,因此执行速度快。可是伪代码能够在不一样的平台下运行。具体相关内容参考oracle文档。
user_objects 包含当前用户全部的对象的信息
user_souce 包含原始代码

局部子程序
* 局部子程序能够被声明为存储子程序声明段的一部分。
* 任何局部子程序必须在声明段的最后进行声明。
DECLARE
...
FUNCTION ...
END
BEGIN
...
END;
* 预先声明,子程序能够预先声明
DELCARE
FUNCTION ...;
...
FUNCTION ... IS
...
END
BEGIN
...

局部子程序通常用在避免单个语句块中的代码重复。

可使用DBMS_SHARED_POOL.KEEP 包过程把已编译伪代码锁定在共享池。

10.2 存储子程序和包的考虑事项
子程序依赖性,当子程序中的表或引用的其余子程序有变更的时候,这个子程序就变为无效。引用该子程序的子程序也会无效。
可是若是引用的子程序是远程的话,则当子程序改变时,当前程序不会变成无效的。
包有特例,包体中的函数或过程的改变,不会影响包头(除非须要改动包头)。因此引用包头的子程序不会受到影响。
决定一个子程序是否须要从新编译,有2中方法: 时间戳 和 签名。
将参数 REMOTE_DEPENDENCIES_MODE参数设置为 SIGNATURE。 可使用签名模式。
ALTER PROCEDURE procedure_name COMPILE
ALTER FUNCTION function_name COMPILE
ALTER PACKAGE package_name COMPLIE
ALTER PACKAGE package_name COMPLIE SPECIFICATION
ALTER PACKAGE package_name COMPLIE BODY

在包头声明的变量具备全局范围,包的状态一直保持到会话结束。
仔细看下面的例子,区分可串行复用的包和不可串行复用的包的区别。pragma serially_reusable
-----------------------------------------------------------------------------------------------
SQL> create or replace package test_pack as
2 procedure test1;
3 end test_pack;
4 /

Package created
SQL> create or replace package body test_pack as
2 num int := 1;
3 procedure test1 is
4 begin
5 num:=num+1;
6 dbms_output.put_line(num);
7 end test1;
8 end test_pack;
9 /

Package body created

SQL> exec test_pack.test1;
2

PL/SQL procedure successfully completed

SQL> exec test_pack.test1;
3

PL/SQL procedure successfully completed

SQL> exec test_pack.test1;
4

PL/SQL procedure successfully completed

SQL>

SQL> create or replace package test_pack as
2 pragma serially_reusable;
3 procedure test1;
4 end test_pack;
5 /

Package created

SQL> create or replace package body test_pack as
2 pragma serially_reusable;
3 num int := 1;
4 procedure test1 is
5 begin
6 num:=num+1;
7 dbms_output.put_line(num);
8 end test1;
9 end test_pack;
10 /

Package body created

SQL> exec test_pack.test1;
2

PL/SQL procedure successfully completed

SQL> exec test_pack.test1;
2

PL/SQL procedure successfully completed

-----------------------------------------------------------------------------------------------
可串行复用的包: 运行时状态保存在共享存储器中,并在每一次数据库调用后释放 使用的最大存储器与同时使用该包的用户数成正比。
不可串行复用的包:运行时状态保存在过程存储器中,并在整个数据库会话中持续 使用的最大存储器与同时登录的用户数成正比,存储器通常会高得多。

子程序使用显示地(而不是经过角色)授予其全部者的特权而执行。
由于PL/SQL使用早期绑定,可是因为角色的不肯定性,因此在存储过程、函数、包和触发器内部,全部角色都被禁止。

CREATE [OR REPLACE] [FUNCTION|PROCEDURE|PACKAGE] ...
...
[AUTHID {CURRENT_USER|DEFINER}] {IS|AS}
若是声明 CURRENT_USER 则对象将拥有调用者的权限。若是指定 DEFINER,那么对象将拥有定义者的权限。

------------------------------------------------------------------------------------------------------------
SQL> create or replace procedure p_test2
2 authid current_user as
3 begin
4 dbms_output.put_line('this is p_test2');
5 end;
6 /

Procedure created

SQL> create or replace procedure p_test1
2 authid current_user as
3 begin
4 p_test2;
5 insert into ipnet.t_test values(1);
6 dbms_output.put_line('this is p_test1');
7 end;
8 /

Procedure created

SQL> exec ipnet.p_test1;
BEGIN ipnet.p_test1; END;

*
ERROR 位于第 1 行:
ORA-06550: 第 1 行, 第 7 列:
PLS-00201: 必须说明标识符 'IPNET.P_TEST1'
ORA-06550: 第 1 行, 第 7 列:
PL/SQL: Statement ignored

ipnet用户赋execute p_test1 的权限给 ipnet1 用户:
SQL> grant execute on p_test1 to ipnet1;

Grant succeeded

ipnet1用户再次执行p_test1:
SQL> exec ipnet.p_test1;
BEGIN ipnet.p_test1; END;

*
ERROR 位于第 1 行:
ORA-00942: 表或视图不存在
ORA-06512: 在"IPNET.P_TEST1", line 5
ORA-06512: 在line 1

ipnet用户赋 insert on t_test1 的权限给 ipnet1 用户:
SQL> grant insert on t_test to ipnet1;

Grant succeeded

ipnet1用户再次执行p_test1:
SQL> exec ipnet.p_test1;
this is p_test2
this is p_test1

PL/SQL 过程已成功完成。

能够看到 对于 p_test1 和 t_test 的权限必须付给ipnet1用户,可是 p_test2 的 execute 权限却不须要付给ipnet1用户。
------------------------------------------------------------------------------------------------------------oracle

10.3 在SQL语句中使用存储函数
函数有四个不一样的纯度等级。
WNDS 不写数据库状态 该函数不修改任何数据库表(使用DML语句)
RNDS 不读数据库状态 该函数不读取任何数据库表(使用SELECT语句)
WNPS 不写包状态 该函数不修改任何封装变量(在赋值语句左边或在FETCH语句中不使用封装变量)
RNPS 不读包状态 该函数不检查任何封装变量(封装变量不在赋值语句右边出现,也不能做为过程或SQL表达式的一部分)

PRAGMA RESTRICT_REFERENCES(subprogram_or_package_name,WNDS[,WNPS][,RNDS][,RNPS])
在8i之前,打包函数须要编译指示。8i以后,数据库将在运行时验证函数的纯度等级。


CREATE OR REPLACE PACKAGE student as
FUNCTION FullName(p_studentid IN students.ID%TYPE) RETURN VARCHAR2;
PRAGMA RESTRICT_REFERENCES(FullName,WNDS,WNPS,RNPS);
...
END ;

DEFAULT 关键字
在SQL中调用函数时,必须输入全部的参数,不能使用默认参数方式。

在Oracle8i以前,从DML语句中调用的函数不能更新数据库,可是8i以后能够,只要不是修改该DML语句修改的对象表。


10.4 在共享池中的锁定
DBMS_SHARED_POOL
.KEEP(name VARCHAR2,flag CHAR) 用来在共享池中锁定对象。包、触发器、序列、对象类型和Java对象。
name 对象的名称
flag P-包、函数或过程 Q-序列 R-触发器 T-对象类型
JS-java源代码 JC-java类 JR-java资源 JD-java共享数据
C-SQL游标
.UNKEEP(name VARCHAR2,flag CHAR) 做用和KEEP相反,参数含义同样。
.SIZE(minsize NUMBER) 大小大于minsize的对象将被返回。
.ABORTED_REQUEST_THRESHOLD(threshold_size NUMBER)
一旦掉用,Oracle将不会开始从池中释放对象,除非至少须要threshold_size个字节。函数

来自 “ ITPUB博客 ” ,连接:http://blog.itpub.net/133835/viewspace-922043/,如需转载,请注明出处,不然将追究法律责任。 学习

转载于:http://blog.itpub.net/133835/viewspace-922043/this