技术开发 频道

了解DB2 Version 9.5中的全局变量


示例

    现在您已经了解了如何使用全局变量执行简单的操作,本节将提供一些有趣的场景以展示如何使用它们。 

    使用全局变量关闭触发器以进行维护 

    全局变量的一项有趣应用就是控制触发器的行为。例如,如果您的表具有以下触发器:

CREATE TRIGGER validate_t
BEFORE INSERT ON T
REFERENCING NEW AS N FOR EACH ROW
WHEN (N.ORDER_DATE < CURRENT TIMESTAMP – 7 DAYS)
SIGNAL SQLSTATE ‘38000’
SET MESSAGE TEXT = ‘ORDER DATE TOO OLD’; 

    如果 DBA 希望进行一些维护并向表插入一些较旧的数据,他必须阻止其他用户向表插入新的数据、删除触发器、执行维护、重新创建触发器,维护完之后才能允许用户插入数据。 

    通过创建可以控制触发器行为的全局变量,可以简化这个任务并提高并发行。要执行维护并向表插入较旧的数据,您将使用全局变量并完成以下步骤:

1. 创建一个全局变量:

CREATE VARIABLE schema1.disableTriggers CHAR(1) DEFAULT ‘N’


2. 向所有用户授予对变量的读权限:

GRANT READ on VARIABLE shema1.disableTriggers TO PUBLIC


3. 只向 DBA 用户 ID 授予对变量的写权限:

GRANT WRITE ON VARIABLE shema1.disableTriggers TO dba_user


4. 创建触发器(在 WHEN 子句中添加对全局变量的检查):

CREATE TRIGGER validate_t
BEFORE INSERT ON T
REFERENCING NEW AS N FOR EACH ROW
WHEN (schema1.disableTriggers = 'N' AND N.ORDER_DATE< CURRENT TIMESTAMP - 7 DAYS)
SIGNAL SQLSTATE '38000'
SET MESSAGE TEXT = 'ORDER DATE TOO OLD': 


    之后,如果需要对表执行任何维护,您所需做的就是修改会话中全局变量的值:

SET disable_triggers = ‘Y’; 


    修改了全局变量的值之后就可以执行维护了,同时其他用户可以向表插入新的纪录。维护完成之后,将值改回来即可:

SET disable_triggers = ‘N’;


使用全局变量降低复杂性并提升性能 

    在使用全局变量之前,可以使用它们计算变量值,从而可提升其他 SQL 实体的性能并降低复杂性。例如,通过调用一个可以为 SESSION_USER 特殊寄存器提供值的函数来设置变量,使用它取回当前用户的部门编号。视图可以在谓词中使用该全局变量的值,从而只选择分配给用户所在部门的行。视图不需要包含子查询。因此,降低了复杂性并且视图操作更加高效和快捷。

1. 像以前一样,创建全局变量:

CREATE VARIABLE schema1.gv_deptno INTEGER
DEFAULT(get_deptno (SESSION_USER))


2. 或者,在变量创建定义中使用 fullselect 来代替函数调用:

CREATE VARIABLE schema1.gv_deptno INTEGER DEFAULT
((SELECT deptno FROM hr.employees WHERE empUser = SESSION_USER));


3. 创建视图:

CREATE VIEW schema1.emp_filtered AS SELECT * FROM employee
WHERE deptno = schema1.gv_deptno;


4. 调整权限以使其他用户只能在视图中进行选择:

REVOKE ALL ON schema1.emp_filtered FROM PUBLIC
GRANT SELECT ON schema1.emp_filtered TO PUBLIC


因此,使用该视图的任何用户只能够查看视图中属于所在部门的行。

名称解析 

    全局变量名称由两部分构成。如果在没有使用模式名情况下引用全局变量,则使用 SQL 路径协助解析名称。对于静态 SQL 语句,使用 FUNCPATH 绑定选项指定 SQL 路径。对于动态 SQL 语句,SQL 路径为 CURRENT PATH 特殊寄存器的值。这与函数、过程和数据类型使用的是相同的算法。 

    只有确定变量名与列、SQL 变量、SQL 参数、转换变量或特殊寄存器的名称不匹配时,才能将它视为一个全局变量。虽然 CURRENT PATH 特殊寄存器可能包含多个模式,用户也可能不具备足够的权限访问一个或多个模式中的对象。函数和过程使用 EXECUTE 权限执行例程解析 —— 例如,如果用户不具备 EXECUTE 权限访问最符合指定内容的例程,DB2 将移至列表中下一个最符合的例程。但不能对 VARIABLES 执行这个操作。如果用户不具备针对某个变量的 READ(或 WRITE)权限,DB2 不会移至下一个模式 —— 而仅仅是不能进行编辑。 

    在对函数和数据类型使用全局变量时,必要时可以使用保守的绑定语义。在很多实例中,在处理语句时将解析全局变量,并且数据库管理器必须能够重复这种解析。这条规则适用于

-包中的静态 DML 语句
-视图
-触发器
-SQL 例程 

    对于包中的静态 DML 语句,将在进行绑定时解析全局变量。在视图、触发器和 SQL 例程中,将在创建数据库对象时进行解析。 

    在对全局变量进行解析时,如果同一个 SQL 路径中的不同模式新添了一个具有相同名称的全局变量,则可能会更改行为。为避免这个问题,数据库管理器将在必要时应用保守的绑定语义。这意味着,在 SQL 路径中,只有在最后一次显式绑定时间戳之前定义的全局变量才会进行名称解析。 

    如果 DML SQL 语句、触发器、视图或例程内引用了一个全局变量,将为语句或对象记录关于完全限定全局变量名的依赖关系。同样,如果可以的话,将对语句使用的授权 ID 进行检查,以查看是否拥有对全局变量的 READ 权限。

事务 

    如果全局变量是在会话内创建,则其他会话不能使用它,除非已经提交了这个工作单元。然而,在创建全局变量的会话的内部,在提交工作单元之前也可以使用新创建的变量。这种行为与其他创建对象(例如表)是一致的。 

    对全局变量值的设定是非事务性的。因此,应用程序无法回滚全局变量的值设置。注意以下事项: 

    如果回滚全局变量的创建,那么该变量将不再存在。
如果要回滚全局变量的删除,变量值将为删除前的值(如果在删除前会话引用了全局变量,则为旧值,如果之前没有发生引用,则为未初始化的值)。
XA 交互 

    全局变量的范围被规定为 XA 事务内的单一会话级别,并且不可用于其他加入事务的会话。 

    全局变量是非事务性状态对象。因此,在 XA 环境中(包括紧密耦合的事务和松散耦合的事务),全局变量对象(实体和值)不会针对 XAend 发生更改(对诸如 XAstart、XArollback 等其他 XA API 也是如此)。 

    注意:和事务性状态对象一样,DB2 实现了声明式的全局临时表。因此,在执行以下 XA API 时,将删除声明式全局临时表。

XArollback

XAend(SUCCESS)

XAstart(NOFLAGS)

XAstart(JOIN)


全局变量审计 

    您可以对全局变量的信息进行审计。将生成如下所示的审计记录:

-在对变量执行创建或删除操作时生成 OBJMAINT 审计记录
-当对全局变量授予或撤销权限时生成 SECMAINT 审计记录
-当对全局变量检查权限时生成 CHECKING 审计记录

对照 Oracle 包变量 

    在将应用程序从 Oracle 迁移到 DB2 时,开发人员发现 DB2 的新全局变量支持非常有用,因为 Oracle 中经常会使用包变量。要迁移到 DB2,将包名映射为模式名并使用特定的模式创建变量。下面的示例演示了这一点:

示例 1. 为数值数据类型创建变量

Oracle CREATE PACKAGE trans_data AS min_balance CONSTANT REAL := 10.00; number_processed INT; END trans_data; / DB2 CREATE SCHEMA trans_data! CREATE VARIABLE trans_data.min_balance DOUBLE DEFAULT (10.00)! CREATE VARIABLE trans_data.number_processed INTEGER!

示例 2. 在存储过程中使用变量

Oracle

CREATE OR REPLACE PACKAGE emp_actions AS PROCEDURE hire_employee ( ename VARCHAR2, job VARCHAR2, mgr NUMBER, sal NUMBER, comm NUMBER, deptno NUMBER); END emp_actions; Empname VARCHAR2; / CREATE OR REPLACE PACKAGE BODY emp_actions AS PROCEDURE hire_employee ( ename VARCHAR2, job VARCHAR2, mgr NUMBER, sal NUMBER, comm NUMBER, deptno NUMBER) IS BEGIN INSERT INTO emp VALUES (empno_seq.NEXTVAL, empname, job, mgr, SYSDATE, sal, comm, deptno); END hire_employee; END emp_actions; /

DB2

CREATE SCHEMA emp_actions! CREATE VARIABLE emp_actions.empname VARCHAR(4000)! CREATE PROCEDURE emp_actions.hire_employee (ename VARCHAR(4000), job VARCHAR(4000), mgr FLOAT, sal FLOAT, comm FLOAT, deptno FLOAT ) LANGUAGE SQL BEGIN INSERT INTO emp VALUES (empno_seq.NEXTVAL, emp_actions.empname, job,mgr, CURRENT TIMESTAMP , sal,comm,deptno); END!

示例 3. 为更加复杂的数据类型创建变量

Oracle

CREATE OR REPLACE PACKAGE uw_constants IS cStartDate CONSTANT DATE := TO_DATE('07-JAN-2006'); cInstructor CONSTANT VARCHAR2(30) := 'A. Morgan'; cPi CONSTANT NUMBER(8,7) := 3.1415926; END uw_constants; /

DB2

CREATE SCHEMA uw_constants! CREATE VARIABLE uw_constants.cStartDate TIMESTAMP DEFAULT (TIMESTAMP('2006-01-07-00.00.00.000000'))! CREATE VARIABLE uw_constants.cInstructor VARCHAR(30) DEFAULT ‘A.Morgan’!
0
相关文章