分享

乔客在线 - 数据库技术 - [转帖]用约束和触发器实施商业规则

 qzg589 2005-09-09
 [转帖]用约束和触发器实施商业规则
  在商界,我们的确通常需要确保始终实施某些规则。例如,参与项目的雇员必须被雇用。或者想要某些事件有计划地发生。例如,如果销售员售出一批商品,则应增加其佣金。 
  
  DB2 通用数据库为此提供了一套有用的方法。 唯一约束是禁止在表的一列或多列中出现重复值的规则。 参考完整性约束确保在整个指定的表中数据一致性。 表检查约束是一些条件,它们定义为表定义的一部分,限制一列或多列中使用的值。触发器允许您定义一组操作,这些操作通过对指定的表进行删除、插入或更新操作来执行或触发。触发器可用于写入其他表、修改输入值以及发布警报信息。 
  
  第一节提供关键字的概念性概述。接着,通过示例和图表进一步探讨参考完整性、约束以及触发器。 
  
  
  1、关键字
  关键字是可用来标识或存取特定行的一组列。 
  
  由不止一列组成的关键字称为组合关键字。在具有组合关键字的表中,组合关键字中各列的排序不受这些列在表中排序的约束。 
  
  
  唯一关键字
  唯一关键字被定义为它的任何值都不相同。唯一关键字的列不能包含空值。在执行 INSERT 和 UPDATE 语句期间,数据库管理程序强制执行该约束。一个表可以有多个唯一关键字。唯一关键字是可选的,并且可在 CREATE TABLE 或 ALTER TABLE 语句中定义。 
  
  
  主关键字
  主关键字是一种唯一关键字,表定义的一部分。一个表不能有多个主关键字,并且主关键字的列不能包含空值。主关键字是可选的,并且可在 CREATE TABLE 或 ALTER TABLE 语句中定义。 
  
  
  外部关键字
  外部关键字在参考约束的定义中指定。一个表可以有零个或多个外部关键字。如果组合外部关键字的值的任何部分为空,则该值为空。外部关键字是可选的,并且可在 CREATE TABLE 语句或 ALTER TABLE 语句中定义。 
  
  
  2、唯一约束
  唯一约束确保关键字的值在表中是唯一的。唯一约束是可选的,并且可以通过使用指定 PRIMARY KEY 或 UNIQUE 子句的 CREATE TABLE 或 ALTER TABLE 语句来定义唯一约束。例如,可在一个表的雇员编号列上定义一个唯一约束,以确保每个雇员有唯一的编号。 
  
  
  3、参考完整性约束
  通过定义唯一约束和外部关键字,可以定义表与表之间的关系,从而实施某些商业规则。唯一关键和外部关键字约束的组合通常称为参考完整性约束。外部关键字所引用的唯一约束称为父关键字。外部关键字表示特定的父关键字,或与特定的父关键字相关。例如,某规则可能规定每个雇员(EMPLOYEE 表)必须属于某现存的部门(DEPARTMENT 表)。因此,将 EMPLOYEE 表中的“部门号”定义为外部关键字,而将 DEPARTMENT 表中的“部门号”定义为主关键字。下列图表提供参考完整性约束的直观说明。 
  
  图 4. 外部约束和主约束定义关系并保护数据


  4、表检查约束
  表检查约束指定对于表的每行都要进行判定的条件。可对个别列指定检查约束。可使用 CREATE 或 ALTER TABLE 语句添加检查约束。 
  
  下列语句创建具有下列约束的表: 
  
  部门编号的值必须在范围 10 至 100 内 
  雇员的职务只能为下列之一: "Sales"、"Mgr"或"Clerk" 
  1986 年之前雇用的每个雇员的工资必须超过 $40,500。 
  
   
     CREATE TABLE EMP
        (ID      SMALLINT NOT NULL,
        NAME     VARCHAR(9),
        DEPT     SMALLINT CHECK (DEPT BETWEEN 10 AND 100),
        JOB     CHAR(5)  CHECK (JOB IN (‘Sales‘, ‘Mgr‘, ‘Clerk‘)),
        HIREDATE   DATE,
        SALARY    DECIMAL(7,2),
        COMM     DECIMAL(7,2),
        PRIMARY KEY (ID),
        CONSTRAINT YEARSAL CHECK (YEAR(HIREDATE) >= 1986 OR SALARY > 40500) )
  
  仅当条件判定为假时才会违反约束。例如,如果插入行的 DEPT 为空值,则插入继续进行而不出错,尽管 DEPT 的值应该象约束中定义的那样在 10 和 100 之间。 
  
  下列语句将一个约束添加至名为 COMP 的 EMPLOYEE 表中,该约束为雇员的总报酬必须超过 $15,000: 
  
   
     ALTER TABLE EMP
      ADD CONSTRAINT COMP CHECK (SALARY + COMM > 15000)
  
  将检查表中现存的行以确保这些行不违反新约束。可通过使用如下的 SET CONSTRAINTS 语句将此检查延期: 
  
     SET CONSTRAINTS FOR EMP OFF
     ALTER TABLE EMP ADD CONSTRAINT COMP CHECK (SALARY + COMM > 15000)
     SET CONSTRAINTS FOR EMP IMMEDIATE CHECKED
   
  
  首先使用 SET CONSTRAINTS 语句以延期对表的约束检查。然后可将一个或多个约束添加至表而不检查这些约束。接着再次发出 SET CONSTRAINTS 语句,反过来将约束检查打开并执行任何延期的约束检查。 
  
  
  5、触发器
  一个触发器定义一组操作,这组操作通过修改指定基表中数据的操作来激活。 
  
  可使用触发器来执行对输入数据的验证;自动生成新插入行的值;为了交叉引用而读取其他表;为了审查跟踪而写入其他表;或通过电子邮件信息支持警报。使用触发器将导致应用程序开发及商业规则的全面实施更快速并且应用程序和数据的维护更容易。 
  
  DB2 通用数据库支持几种类型的触发器。可定义触发器在 DELETE、INSERT 或 UPDATE 操作之前或之后激活。每个触发器包括一组称为触发操作的 SQL 语句,这组语句可包括一个可选的搜索条件。 
  
  可进一步定义后触发器以对每一行都执行触发操作,或对语句执行一次触发操作,而前触发器总是对每一行都执行触发操作。 
  
  在 INSERT、UPDATE 或 DELETE 语句之前使用触发器,以便在执行触发操作之前检查某些条件,或在将输入值存储在表中之前更改输入值。使用后触发器,以便在必要时传播值或执行其他任务,如发送信息等,这些任务可能是触发器操作所要求的。 
  
  下列示例说明了前触发器和后触发器的使用。考虑一个记录并跟踪股票价格波动的应用程序。该数据库包含两个表,CURRENTQUOTE 和 QUOTEHISTORY,定义如下: 
  
   
     CREATE TABLE CURRENTQUOTE
     (SYMBOL VARCHAR(10),
     QUOTE DECIMAL(5,2),
     STATUS VARCHAR(9))
     
     CREATE TABLE QUOTEHISTORY
     (SYMBOL VARCHAR(10),
     QUOTE DECIMAL(5,2),
     TIMESTAMP TIMESTAMP)
  
  当使用如下语句更新 CURRENTQUOTE 的 QUOTE 列时: 
  
   
     UPDATE CURRENTQUOTE
      SET QUOTE = 68.5
      WHERE SYMBOL = ‘IBM‘
  
  应更新 CURRENTQUOTE 的 STATUS 列以反映股票是否: 
  
  在升值 
  处于本年度的新高 
  在下跌 
  处于本年度的新低 
  价位稳定 
  这通过使用下列前触发器来实现: 
  
  (1) 
  
     CREATE TRIGGER STOCK_STATUS
      NO CASCADE BEFORE UPDATE OF QUOTE ON CURRENTQUOTE
      REFERENCING NEW AS NEWQUOTE OLD AS OLDQUOTE
     FOR EACH ROW MODE DB2SQL                  
  
  (2) 
  
     SET NEWQUOTE.STATUS =
  
  (3) 
  
       CASE
  
  (4) 
  
        WHEN NEWQUOTE.QUOTE >=
             (SELECT MAX(QUOTE)
               FROM QUOTEHISTORY     
               WHERE SYMBOL = NEWQUOTE.SYMBOL         
               AND YEAR(TIMESTAMP) = YEAR(CURRENT DATE) )   
        THEN ‘High‘
  
  (5) 
  
       WHEN NEWQUOTE.QUOTE <=               
             (SELECT MIN(QUOTE)
               FROM QUOTEHISTORY
               WHERE SYMBOL = NEWQUOTE.SYMBOL            
               AND YEAR(TIMESTAMP) = YEAR(CURRENT DATE) )   
       THEN ‘Low‘
  
  (6) 
  
       WHEN NEWQUOTE.QUOTE > OLDQUOTE.QUOTE
         THEN ‘Rising‘
       WHEN NEWQUOTE.QUOTE < OLDQUOTE.QUOTE            
         THEN ‘Dropping‘
       WHEN NEWQUOTE.QUOTE = OLDQUOTE.QUOTE
         THEN ‘Steady‘
     END                         
   
  
  
  (1) 
  此代码块将名为 STOCK_STATUS 的触发器定义为一个应该在更新 CURRENTQUOTE 表的 QUOTE 列之前激活的触发器。第二行指定,在将 CURRENTQUOTE 表的实际更新所引起的任何更改应用于数据库之前,要应用触发操作。第二行也意味着触发操作将不会激活任何其他触发器。第三行指定一些名称,必须将这些名称作为列名的限定符用于新值 (NEWQUOTE) 和旧值 (OLDQUOTE)。用这些相关名(NEWQUOTE 和 OLDQUOTE)限定的列名称为转换变量。第四行表示应对每一行都执行触发操作。 
  
  (2) 
  这标记此触发器的触发操作中第一个也是唯一的一个 SQL 语句的开始。 SET 转换变量语句在一个触发器中用来将值赋给表的行中的列,该表正在由激活该触发器的语句进行更新。此语句正将一个值赋给 CURRENTQUOTE 表的 STATUS 列。 
  
  (3) 
  该赋值语句右边使用的表达式为 CASE 表达式。 CASE 表达式扩充为 END 关键字。 
  
  (4) 
  第一种情况检查新报价 (NEWQUOTE.QUOTE) 是否超过当前日历年度中股票符号的最高价。子查询正在使用由跟在后面的后触发器更新的 QUOTEHISTORY 表。 
  
  (5) 
  第二种情况检查新报价 (NEWQUOTE.QUOTE) 是否小于当前日历年度中股票符号的最低价。子查询正在使用由跟在后面的后触发器更新的 QUOTEHISTORY 表。 
  
  (6) 
  最后三种情况将新报价 (NEWQUOTE.QUOTE) 与表 (OLDQUOTE.QUOTE) 中的报价比较,以确定新报价是大于、小于还是等于旧报价。 SET 转换变量语句在此处结束。 
  除了更新 CURRENTQUOTE 表中的项之外,还需要通过将新报价连同时间戳记一起复制到 QUOTEHISTORY 表中来创建一个审查记录。这通过使用下列后触发器来实现: 
  
  (1) 
  
     CREATE TRIGGER RECORD_HISTORY
     AFTER UPDATE OF QUOTE ON CURRENTQUOTE
     REFERENCING NEW AS NEWQUOTE
     FOR EACH ROW MODE DB2SQL
     BEGIN ATOMIC
  
  (2) 
  
     INSERT INTO QUOTEHISTORY
      VALUES (NEWQUOTE.SYMBOL, NEWQUOTE.QUOTE, CURRENT TIMESTAMP);
     END
  
  
  (1) 
  此代码块将命名为 RECORD_HISTORY 的触发器定义为应该在更新 CURRENTQUOTE 表的 QUOTE 列之后激活的触发器。第三行指定应该作为列名的限定符用于新值 (NEWQUOTE) 的名称。第四行表示应对每一行都执行触发操作。 
  
  (2) 
  此触发器的触发操作包括单个 SQL 语句,该语句使用已更新的行中的数据(NEWQUOTE.SYMBOL 和 NEWQUOTE.QUOTE)和当前的时间戳记将该行插入 QUOTEHISTORY 表。 
  
  CURRENT TIMESTAMP 是包含时间戳记的专用寄存器。专用寄存器中提供了列表和解释。

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多