引用包¶
在包头中声明的对象可以在包外调用,可以从数据触发器、存储子程序、应用程序和各种工具中引用包中的内容。调用的方法和调用单独的过程或函数的方法基本相同,唯一的区别就是要在调用的过程或函数名前加上包的名字(中间用“.”分隔)。
语法:
Package_name.Item_Name -- 全局变量、常量
Package_name.Subprogram_name -- 全局函数、过程
Package_name.Exception_name -- 全局异常
说明:
在包体内,包头中的变量可以直接引用,即可以不用包名为其前缀。当然,也可以使用全名(包名为前缀)进行引用。但是若调用包中的过程和函数,不论公有和私有必须使用包名为前缀,若不加前缀则认为是包外的过程或函数。
使用包中全局变量时的注意事项,执行如下用例
示例1:使用包中变量¶
-- 清理环境
DROP PACKAGE pack;
DROP TABLE tab CASCADE;
create table tab
(
a char,
b int
);
create or replace package pack as
g_var tab.a%TYPE := 'a';
procedure proc;
end;
/
create or replace package body pack as
procedure proc as
begin
dbms_output.put_line(g_var);
end proc;
end;
/
exec pack.proc;
--删除表重新创建新的表,a的类型变为int
drop table tab;
create table tab
(
a int,
b int
);
exec pack.proc;
ERROR, 错误的数值格式 'a'
--删除包
DROP PACKAGE pack;
DROP TABLE tab CASCADE;
应该执行中报错的,这里可以正确执行,与预期不符。
包中全局变量因为类型或者默认值的依赖发生改变进而需要改变的,数据库可能发生不可预知的情况,建议包中全局变量使用constant定义,类型依赖发生变化时,如果发生异常情况使用alter package package_name compile操作可以使包正常使用。
可以在存储过程,函数中引用包中的全局变量、自定义类型。每个会话会有一个包实例,各个会话间的全局变量不会互相影响。使用在包外的过程中引用包中的全局变量时,要使用变量的全名,即包名.变量名,自定义类型也一样。
示例2:使用包中全局变量¶
--清理环境
DROP PROCEDURE proc;
DROP PACKAGE pack;
create or replace package pack is
g_var integer;
function f return integer;
end;
/
create or replace package body pack is
function f return integer is
begin
return g_var;
end;
begin
g_var = 1;
end;
/
CREATE OR REPLACE PROCEDURE proc AS
declare
a integer := pack.g_var;
begin
a = a + pack.g_var;
dbms_output.put_line('a: ' || a);
pack.g_var = pack.g_var + 1;
dbms_output.put_line('pack.g_var: ' || pack.g_var);
end;
/
EXEC proc;
a: 2
pack.g_var: 2
--删除
DROP PROCEDURE proc;
DROP PACKAGE pack;
可以在过程中使用包中定义的类型,支持自定义类型作为包中函数的输入输出参数,返回值。目前还不支持自定义类型作包外函数的输入输出参数和返回值。目前自定义类型支持最大嵌套10层。
示例3:使用包中自定义类型¶
-- 清理环境
DROP PROCEDURE proc;
DROP PACKAGE pack;
create or replace package pack is
type rec_type is record
(
a int,
b int
);
type nt_type is table of rec_type index by pls_integer;
function func(nt nt_type, i integer) return rec_type;
end;
/
create or replace package body pack is
function func(nt nt_type, i integer) return rec_type is
begin
return nt(i);
end;
end;
/
--包外过程的参数返回值还不支持使用包中自定义类型
create or replace procedure proc is
--过程内部可以使用
rec pack.nt_type;
begin
rec(1).a := 1;
rec(1).b := 2;
rec(2).a := 3;
rec(2).b := 4;
dbms_output.put_line(pack.func(rec, 2).a);
end;
/
exec proc;
--删除包
DROP PROCEDURE proc;
DROP PACKAGE pack;