panwei 文檔管理

從正面看,是偉大的神(God),從反面看,是卑鄙小人(dog);其實,人們所犯的罪惡(evil),反過來,正是為了活著(live)。

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理
  17 Posts :: 1 Stories :: 3 Comments :: 1 Trackbacks

 

触发器是一种特殊类型的存储过程,当对数据库进行UPDATE,DELETE或INSERT时,触发器会生效.触发器可以查询其它表,而且可以包含复杂的 SQL 语句。


创建触发器语法:
CREATE TRIGGER trigger_name
ON { table | view }
[ WITH ENCRYPTION ]
{
{ { FOR | AFTER | INSTEAD OF } { [ INSERT ] [ , ] [ UPDATE ] }
[ WITH APPEND ]
[ NOT FOR REPLICATION ]
AS
[ { IF UPDATE ( column )
[ { AND | OR } UPDATE ( column ) ]
[ ...n ]
| IF ( COLUMNS_UPDATED ( ) { bitwise_operator } updated_bitmask )
{ comparison_operator } column_bitmask [ ...n ]
} ]
sql_statement [ ...n ]
}
}
使用触发器的优点
• 触发器是自动的:它们在对表的数据作了任何修改(比如手工输入或者应用程序采取的操作)之后立即被激活。
• 触发器可以通过数据库中的相关表进行层叠更改。例如,可以在 titles 表的 title_id 列上写入一个删除触发器,以使其它表中的各匹配行采取删除操作。该触发器用 title_id 列作为唯一键,在 titleauthor、sales 及 roysched 表中对各匹配行进行定位。
• 触发器可以强制限制,这些限制比用 CHECK 约束所定义的更复杂。与 CHECK 约束不同的是,触发器可以引用其它表中的列。例如,触发器可以回滚试图对价格低于 10 美元的书(存储在 titles 表中)应用折扣(存储在 discounts 表中)的更新。


定义一个无论何时用INSERT语句向表中插入数据时都会执行的触发器。

  当触发INSERT触发器时,新的数据行就会被插入到触发器表和inserted表中。inserted表是一个逻辑表,它包含了已经插入的数据行的一个副本。inserted表包含了INSERT语句中已记录的插入动作。inserted表还允许引用由初始化INSERT语句而产生的日志数据。触发器通过检查inserted表来确定是否执行触发器动作或如何执行它。inserted表中的行总是触发器表中一行或多行的副本。

  日志记录了所有修改数据的动作(INSERT、UPDATE和DELETE语句),但在事务日志中的信息是不可读的。然而,inserted表允许你引用由INSERT语句引起的日志变化,这样就可以将插入数据与发生的变化进行比较,来验证它们或采取进一步的动作。也可以直接引用插入的数据,而不必将它们存储到变量中。

  示例

  在本例中,将创建一个触发器。无论何时订购产品(无论何时向Order Details表中插入一条记录),这个触发器都将更新Products表中的一列(UnitsInStock)。用原来的值减去订购的数量值即为新值。
USE Northwind
CREATE TRIGGER OrdDet_Insert
ON [Order Details]
FOR INSERT
AS
UPDATE P SET
UnitsInStock = P.UnitsInStock – I.Quantity
FROM Products AS P INNER JOIN Inserted AS I
ON P.ProductID = I.ProductID

  DELETE触发器的工作过程

  当触发DELETE触发器后,从受影响的表中删除的行将被放置到一个特殊的deleted表中。deleted表是一个逻辑表,它保留已被删除数据行的一个副本。deleted表还允许引用由初始化DELETE语句产生的日志数据。

  使用DELETE触发器时,需要考虑以下的事项和原则:
•当某行被添加到deleted表中时,它就不再存在于数据库表中;因此,deleted表和数据库表没有相同的行。
•创建deleted表时,空间是从内存中分配的。deleted表总是被存储在高速缓存中。
•为DELETE动作定义的触发器并不执行TRUNCATE TABLE语句,原因在于日志不记录TRUNCATE TABLE语句。

  示例
    在本例中,将创建一个触发器,无论何时删除一个产品类别(即从Categories表中删除一条记录),该触发器都会更新Products表中的Discontinued列。所有受影响的产品都标记为1,标示不再使用这些产品了。
USE Northwind
CREATE TRIGGER Category_Delete
ON Categories
FOR DELETE
AS
UPDATE P SET Discontinued = 1
FROM Products AS P INNER JOIN deleted AS d
ON P.CategoryID = d.CategoryID

  UPDATE触发器的工作过程

  可将UPDATE语句看成两步操作:即捕获数据前像(before image)的DELETE语句,和捕获数据后像(after image)的INSERT语句。当在定义有触发器的表上执行UPDATE语句时,原始行(前像)被移入到deleted表,更新行(后像)被移入到inserted表。

  触发器检查deleted表和inserted表以及被更新的表,来确定是否更新了多行以及如何执行触发器动作。

  可以使用IF UPDATE语句定义一个监视指定列的数据更新的触发器。这样,就可以让触发器容易的隔离出特定列的活动。当它检测到指定列已经更新时,触发器就会进一步执行适当的动作,例如发出错误信息指出该列不能更新,或者根据新的更新的列值执行一系列的动作语句。

  语法
  例1

  本例阻止用户修改Employees表中的EmployeeID列。
USE Northwind
GO
CREATE TRIGGER Employee_Update
ON Employees
FOR UPDATE
AS
IF UPDATE (EmployeeID)
BEGIN
RAISERROR ('Transaction cannot be processed.\
***** Employee ID number cannot be modified.', 10, 1)
ROLLBACK TRANSACTION
END

  INSTEAD OF触发器的工作过程

  可以在表或视图上指定INSTEAD OF触发器。执行这种触发器就能够替代原始的触发动作。INSTEAD OF触发器扩展了视图更新的类型。对于每一种触发动作(INSERT、UPDATE或 DELETE),每一个表或视图只能有一个INSTEAD OF触发器。

  INSTEAD OF触发器被用于更新那些没有办法通过正常方式更新的视图。例如,通常不能在一个基于连接的视图上进行DELETE操作。然而,可以编写一个INSTEAD OF DELETE触发器来实现删除。上述触发器可以访问那些如果视图是一个真正的表时已经被删除的数据行。将被删除的行存储在一个名为deleted的工作表中,就像AFTER触发器一样。相似地,在UPDATE INSTEAD OF触发器或者INSERT INSTEAD OF触发器中,你可以访问inserted表中的新行。

  不能在带有WITH CHECK OPTION定义的视图中创建INSTEAD OF触发器。
CHECK 约束
CHECK 约束指定可由表中一列或多列接受的数据值或格式。例如,可以要求 authors 表的 zip 列只允许输入五位数的数字项。
可以为一个表定义许多 CHECK 约束。可以使用"表"属性页创建、修改或删除每个 CHECK 约束。
约束
约束使您得以定义 Microsoft® SQL Server™ 2000 自动强制数据库完整性的方式。约束定义关于列中允许值的规则,是强制完整性的标准机制。使用约束优先于使用触发器、规则和默认值。查询优化器也使用约束定义生成高性能的查询执行计划。
约束类
SQL Server 2000 支持五类约束。
• NOT NULL 指定不接受 NULL 值的列。
• CHECK 约束对可以放入列中的值进行限制,以强制执行域的完整性。
CHECK 约束指定应用于列中输入的所有值的布尔(取值为 TRUE 或 FALSE)搜索条件,拒绝所有不取值为 TRUE 的值。可以为每列指定多个 CHECK 约束。下例显示名为 chk_id 约束的创建,该约束确保只对此关键字输入指定范围内的数字,以进一步强制执行主键的域。
CREATE TABLE cust_sample
    (
    cust_id                int        PRIMARY KEY,
    cust_name            char(50),
    cust_address            char(50),
    cust_credit_limit    money,
    CONSTRAINT chk_id CHECK (cust_id BETWEEN 0 and 10000 )
    )
• UNIQUE 约束在列集内强制执行值的唯一性。
对于 UNIQUE 约束中的列,表中不允许有两行包含相同的非空值。主键也强制执行唯一性,但主键不允许空值。UNIQUE 约束优先于唯一索引。
• PRIMARY KEY 约束标识列或列集,这些列或列集的值唯一标识表中的行。
在一个表中,不能有两行包含相同的主键值。不能在主键内的任何列中输入 NULL 值。在数据库中 NULL 是特殊值,代表不同于空白和 0 值的未知值。建议使用一个小的整数列作为主键。每个表都应有一个主键。
一个表中可以有一个以上的列组合,这些组合能唯一标识表中的行,每个组合就是一个候选键。数据库管理员从候选键中选择一个作为主键。例如,在 part_sample 表中,part_nmbr 和 part_name 都可以是候选键,但是只将 part_nmbr 选作主键。
CREATE TABLE part_sample
            (part_nmbr        int            PRIMARY KEY,
            part_name        char(30),
            part_weight        decimal(6,2),
            part_color        char(15) )
• FOREIGN KEY 约束标识表之间的关系。
一个表的外键指向另一个表的候选键。当外键值没有候选键时,外键可防止操作保留带外键值的行。在下例中,order_part 表建立一个外键引用前面定义的 part_sample 表。通常情况下,order_part 在 order 表上也有一个外键,下面只不过是一个简单示例。
CREATE TABLE order_part
        (order_nmbr        int,
        part_nmbr        int
            FOREIGN KEY REFERENCES part_sample(part_nmbr)
                ON DELETE NO ACTION,
        qty_ordered        int)
GO
如果一个外键值没有候选键,则不能插入带该值(NULL 除外)的行。如果尝试删除现有外键指向的行,ON DELETE 子句将控制所采取的操作。ON DELETE 子句有两个选项:
• NO ACTION 指定删除因错误而失败。
• CASCADE 指定还将删除包含指向已删除行的外键的所有行。
如果尝试更新现有外键指向的候选键值,ON UPDATE 子句将定义所采取的操作。它也支持 NO ACTION 和 CASCADE 选项。
列约束和表约束
约束可以是列约束或表约束:
• 列约束被指定为列定义的一部分,并且仅适用于那个列(前面的示例中的约束就是列约束)。
• 表约束的声明与列的定义无关,可以适用于表中一个以上的列。
当一个约束中必须包含一个以上的列时,必须使用表约束。
例如,如果一个表的主键内有两个或两个以上的列,则必须使用表约束将这两列加入主键内。假设有一个表记录工厂内的一台计算机上所发生的事件。假定有几类事件可以同时发生,但不能有两个同时发生的事件属于同一类型。这一点可以通过将 type 列和 time 列加入双列主键内来强制执行。
CREATE TABLE factory_process
   (event_type   int,
   event_time   datetime,
   event_site   char(50),
   event_desc   char(1024),
CONSTRAINT event_key PRIMARY KEY (event_type, event_time) )

 

posted on 2006-05-19 03:47  panwei  阅读(...)  评论(...编辑  收藏