package中全局变量特性

    Oracle中的package对象是其他数据库中所不存在的特性之一,这是oracle面向对象编程的一种体现.我们可以像定义面向对象语言的对象一样定义oracle的package.
    并为package定义对应的属性(全局变量)全局变量(可以定义在包头,也可以在包体,赋值一定在包体)和方法(function,procedure).
    package的全局变量在oracle编程过程中有很多有趣并非常实用的作用.比如,我们可以利用这个特性定义带参数的视图,以增加特定情况下(无法通过普通视图完成数据的筛选过程)程序的可维护性,其中的参数就是全局变量,但是得由于封装的缘故,即使是包头中的全局变量,在数据库级包以外的其他对象不公开。
    本文利用几个测试简单描述package的全局变量特性和用法.
    1、oracle中package的全局变量的全局性是基于session级别的.在session级别设置,修改,维护全局变量的过程不会传输到其他的session中.
   
    我们可以这样理解,oracle将package封装为一个类.在每个session第一次调用时为这个类创立一个实例.而session结束后自动释放实例资源.   

CREATE OR REPLACE PACKAGE PKG_TEST
IS
  PROCEDURE P_1(v1 VARCHAR2,v2 VARCHAR2);
  PROCEDURE P_2(v1 VARCHAR2,v2 VARCHAR2);
END;

 

CREATE OR REPLACE PACKAGE BODY PKG_TEST
IS
  G_1 VARCHAR2(20);
  G_2 VARCHAR2(20);
  PROCEDURE P_1(v1 VARCHAR2,v2 VARCHAR2)
  IS
  BEGIN
    G_1 := v1;
    G_2 := v2;
    dbms_output.put_line('G1:'||G_1);
    dbms_output.put_line('G2:'||G_2);
  END;

  PROCEDURE P_2(v1 VARCHAR2,v2 VARCHAR2)
  IS
  BEGIN
    G_1 := v1;
    G_2 := v2;
    dbms_output.put_line('G1:'||G_1);
    dbms_output.put_line('G2:'||G_2);
  END;

BEGIN
  G_1 := 0;
  G_2 := 0;
END PKG_TEST;

第一步:我们在程序包PKG_TEST中定义了两个全局变量G_1和G_2,每次调用pkg_test时,我们将两个数据的值都初始化为0.

第二步, 在session1中执行单步测试过程P_1并传入两个参数v1=1,v2=1.

第三步,另外开启session,调用过程P2.

第四步, 然后回到session1,将过程P_1剩余的代码执行结束.发现输出结果如下.

G1:1

G2:1

结论1:

由于package的全局变量在数据库层次上并不可见是public的,所以每个session都可以认为是一个被实例化了地package对象.在session级别上对全局变量执行的赋值操作并不会被其他session看到.很好地体现了数据的封装性.

2、引用package中的全局变量,database级包外的其它对象虽然可见,但依然无法使用该变量的值.因为这个值为了进行封装,在database级别并不是公用的.

  希望通过下述方式调用pkg_test的全局变量在视图中使用,错误的.

CREATE OR REPLACE VIEW v_test
AS
SELECT decode(pkg_test.G_1,'0','零','非零') FROM dual;

这时,oracle会提示错误.

PKG_TEST.G_1无效的标识符.这是因为pkg_test的全局变量是在package body中定义的,所以这个全局变量对oracle的其他对象不可见.

如果我们修改pkg_test的定义,将全局变量放到package中进行定义,这样我们在v_test中虽然可以看到g_1,但依然无法使用该变量的值.因为这个值为了进行封装,在database级别并不是公用的.

CREATE OR REPLACE PACKAGE PKG_TEST
IS
  G_1 VARCHAR2(20);

  G_2 VARCHAR2(20);

  PROCEDURE P_1(v1 VARCHAR2,v2 VARCHAR2);

  PROCEDURE P_2(v1 VARCHAR2,v2 VARCHAR2);
END;

再次执行刚才的视图定义,看到报错提示为:

ora-06533:PLS-221G_1不是过程或尚未定义.

解决方式如下.

修改pkg_test的定义,为package增加两个函数F_1,F_2,用来返回G_1和G_2的数据,这样的两个函数就可以被其他过程引用了.

CREATE OR REPLACE PACKAGE PKG_TEST
IS
  FUNCTION F_1 RETURN VARCHAR2;
  FUNCTION F_2 RETURN VARCHAR2;
END;

CREATE OR REPLACE PACKAGE BODY PKG_TEST
Is

  G_1 VARCHAR2(20);
  G_2 VARCHAR2(20);

  FUNCTION F_1
  RETURN VARCHAR2
  IS
  BEGIN
    RETURN G_1;
  END;
  FUNCTION F_2
  RETURN VARCHAR2
  IS
  BEGIN
    RETURN G_1;
  END;

BEGIN

  G_1 := 0;

  G_2 := 0;

END PKG_TEST;

这时我们就可以成功执行视图的创建了.

CREATE OR REPLACE VIEW v_test
AS
SELECT decode(pkg_test.F_1,'0','零','非零') F1 FROM dual;

设想一下这个视图会返回的结果:

a、在pkg_test数据包外进行调用时,由于每次调用pkg_test.f_1之前都会将g_1初始化为0,所以一定会得到’零’这个结果.

b、但是如果同一session我们在调用Pkg_test数据包的过程中,再执行视图,则可以预先通过给G_1赋值的不同而得到我们希望得到的

结论2:
    由于oracle的package并没有显式地创建实例,所以package的全局变量跟其他面向对象语言的类的属性还是有区别的.最显著的区别在于这里的全局变量不能作为属性值在其他procedure或者function中进行调用.如果希望达到这样的效果,可以通过在package中定义function来实现.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值