Chinaunix首页 | 论坛 | 博客
  • 博客访问: 671449
  • 博文数量: 845
  • 博客积分: 5000
  • 博客等级: 大校
  • 技术积分: 5015
  • 用 户 组: 普通用户
  • 注册时间: 2008-10-15 16:22
文章分类

全部博文(845)

文章存档

2011年(1)

2008年(844)

我的朋友

分类:

2008-10-15 16:26:29

        在关系数据库系统内部,应用程序和实际数据库之间的主要交互都是以会话或连接的 SQL 语句形式来实现的。过去,为了在相同会话中实现不同 SQL 语句之间的信息共享,发出 SQL 语句的应用程序必须将语句输出参数集(本地变量)的值复制到另一个语句的输入本地变量中。此外,数据库系统本身定义或包含的 SQL 语句,例如用来定义触发器和视图的 SQL 语句,根本不能够访问这些共享信息。

        总之,种种约束限制了关系数据库系统的灵活性,并因此限制了系统用户在数据库内部实现复杂、交互式模型的能力。这类系统的用户不得不在自己的应用程序或 SQL 过程中添加支持逻辑,以便在关系数据库系统中访问和传递用户应用程序信息和内部数据库信息。用户还需对其应用程序逻辑进行增强,以确保被传递和访问的信息的性。

        为克服这种约束并最大化实现关系数据库系统的灵活性,DB2 V9.5 引入了全局变量的概念。通过引入全局变量,用户现在可以在关系数据库内部轻松地构建复杂系统,同时可在同一会话的 SQL 语句之间共享信息,或者使用数据库系统定义或包含的 SQL 语句访问信息。实现这些任务无需任何应用程序逻辑,从而支持信息传递。本文的目的是介绍这种新特性并解释如何使用它才能发挥其潜力。

        首先,了解什么是全局变量以及它涉及的基本操作。然后查看一些有趣的场景,了解全局变量的使用。最后,本文将更加深入地阐述一些与全局变量有关的主题。

        什么是全局变量?

        全局变量表示一个可以使用 SQL 语句访问和修改的可变值。在 DB2 中,这些变量被实现为一种新型数据库对象,其定义保存在数据库编目中。编目中保存的是全局变量的定义而非实际的值,了解这一点非常重要。这样做是因为全局变量具有一个会话(连接)范围。这意味着每个会话都可以使用编目中保存的全局变量,但是每个会话拥有自己的私有值来操作和使用。其他会话都不能访问这个值。

        全局变量的另一重要方面是,当考虑到信息问题时,可以控制对信息的访问。需要有特定的权限才能创建或删除全局变量,以及读取或修改其内容。这条规则同样适用于全局变量的定义 —— 与全局变量相关的权限也在系统编目中进行了定义。

        创建和删除全局变量

        要创建一个全局变量,可以使用新的 CREATE VARIABLE SQL 语句。您需要对模式使用 SYSADM, DBADM 权限或 CREATE_IN。例如,要创建一个全局变量来表示默认的打印机,应该发出如下语句:

         CREATE VARIABLE mySchema.defaultPrinter VARCHAR(30)
        DEFAULT 'Printer001'

        mySchema.defaultPrinter 表示变量的名称。请注意,全局变量的名称由两部分组成,即模式的名称和其中的变量的名称。如果没有具体指定模式,则默认为当前模式。

        VARCHAR(30) 表示变量的数据类型。数据类型可以是 DB2 内置数据类型、独特的类型或引用类型。注意,不能为全局变量指定 CLOB、DBCLOB、BLOB、LONG VARCHAR、LONG VARGRAPHIC、XML、ARRAY 或结构化类型。

        如果在第一次引用全局变量没有为全局变量指定其他值,那么使用 DEFAULT ‘Printer001’ 表示它的默认值。默认指定的子句可以为一个常量、一个特殊的寄存器、另一个全局变量、一个表达式或关键字 NULL。表达式可以是 SQL Reference Guide 的 “Expressions” 部分中定义的任何类型的表达式(请参见 参考资料)。如果没有指定默认值,则初始变量为 NULL。表达式的最大大小为 64K。在第一次引用时,默认表达式将为全局变量计算一个值。只要不修改 SQL 中的数据或不会在 DB2 引擎以外执行任何操作,则可以使用 DB2 允许的任何表达式。此外,表达式在分配时必须与变量数据类型兼容。

        下面列出了其他一些全局变量示例:

        要创建表示用户第一次连接时间的变量,使用以下语句:

         CREATE VARIABLE loginTime TIMESTAMP DEFAULT CURRENT TIMESTAMP

        要创建表示员工所属部门的变量,使用以下语句:

         CREATE VARIABLE schema1.gvDeptno INTEGER DEFAULT
        ((select deptno from hr.employees where empUser = SESSION_USER));

        如果希望创建一个全局变量表示最高级安全级别,使用下面的语句:

         CREATE VARIABLE mySchema.SecurityLevel CHAR(5) DEFAULT NULL

        请注意,一旦创建完毕,全局变量的 length 属性和数据类型将不能更改。此外,您不能更改全局变量定义,包括其默认值。

        如果您不希望再保存全局变量的定义,则需要删除它。删除全局变量和删除其他数据库对象需要使用相同的权限(请参考 SQL Reference 中的完整权限列表)。例如,要删除我们前面创建的表示默认打印机的全局变量,应使用以下语句:

         DROP VARIABLE mySchema.defaultPrinter

        where:

        mySchema.defaultPrinter 是变量的名称。如果没有指定模式,则遵守特定规则来确定模式名称。本文稍后的内容将讨论名称解析。

        请注意,如果函数、方法、触发器或视图中引用了某个全局变量,则不能删除该变量。

        使用全局变量

        创建了全局变量之后,如果拥有相应的权限,数据库中的任何会话都可以使用它。READ 权限用于引用全局变量,而 WRITE 权限用于修改全局变量的值。GRANT 语句允许授权用户对这些权限进行授权,而 REVOKE 语句用于删除这些权限。全局变量的所有者被显式授予了有关该变量的所有权限。

        任何表达式都可以引用全局变量,只要该表达式不需要保持确定性。以下这些情况需要确定性表达式,因此不能使用全局变量:

        -检查约束
        -生成的列的定义
        -刷新直接 Materialized Query Tables (MQTs)
        -如上文所述,每个会话对于给定的全局变量都具有自己的私有值。当在会话中第一次引用时,全局变量将进行实例化来获得其默认值。

        要查询当前用户所在部门的全部员工,使用以下语句:

         SELECT * FROM hr.employees WHERE> deptno = schema1.gvDeptno

        要查询本地变量 hv_depnot 的用户部门编号,使用以下语句:

         EXEC SQL VALUES schema1.gvDeptno INTO :hv_deptno

        要查询用户的部门编号,使用以下语句:

         VALUES schema1.gvDeptno

        可以使用 SET, SELECT INTO, VALUES INTO 语句改变全局变量的值。也可以作为调用语句的 out 或 input 参数的实参进行修改。

        例如,要将 mySchema.defaultPrinter 变量的值修改为 “Printer002”,使用以下语句:

         SET mySchema.defaultPrinter = 'Printer002'

        要修改 schema1.activeEmployees 的值,使用以下语句:

         EXEC SQL SELECT count(*) INTO schema1.activeEmployees
        FROM hr.employees WHERE active = ‘Y’

        示例

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

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

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

         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]   

【责编:michael】

--------------------next---------------------

阅读(249) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~