触发器
触发器是一种特殊类型的存储过程,当使用下面的一种或多种数据修改操作在指定表中对数据进行修改时,触发器会生效:UPDATE、INSERT 或 DELETE。触发器可以查询其它表,而且可以包含复杂的 SQL 语句。它们主要用于强制复杂的业务规则或要求。例如,可以控制是否允许基于顾客的当前帐户状态插入定单。触发器还有助于强制引用完整性,以便在添加、更新或删除表中的行时保留表之间已定义的关系。然而,强制引用完整性的最好方法是在相关表中定义主键和外键约束。如果使用数据库关系图,则可以在表之间创建关系以自动创建外键约束。有关详细信息,请参见表关系。使用触发器的优点
触发器的优点如下: 触发器是自动的:它们在对表的数据作了任何修改(比如手工输入或者应用程序采取的操作)之后立即被激活。
触发器可以通过数据库中的相关表进行层叠更改。例如,可以在 titles 表的 title_id 列上写入一个删除触发器,以使其它表中的各匹配行采取删除操作。该触发器用 title_id 列作为唯一键,在 titleauthor、sales 及 roysched 表中对各匹配行进行定位。
触发器可以强制限制,这些限制比用 CHECK 约束所定义的更复杂。与 CHECK 约束不同的是,触发器可以引用其它表中的列。例如,触发器可以回滚试图对价格低于 10 美元的书(存储在 titles 表中)应用折扣(存储在 discounts 表中)的更新。 

解决方案 »

  1.   

    CREATE TRIGGER
    创建触发器,触发器是一种特殊的存储过程,在用户试图对指定的表执行指定的数据修改语句时自动执行。Microsoft® SQL Server™ 允许为任何给定的 INSERT、UPDATE 或 DELETE 语句创建多个触发器。语法
    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 ] 
        } 
    } 参数
    trigger_name是触发器的名称。触发器名称必须符合标识符规则,并且在数据库中必须唯一。可以选择是否指定触发器所有者名称。Table | view是在其上执行触发器的表或视图,有时称为触发器表或触发器视图。可以选择是否指定表或视图的所有者名称。WITH ENCRYPTION加密 syscomments 表中包含 CREATE TRIGGER 语句文本的条目。使用 WITH ENCRYPTION 可防止将触发器作为 SQL Server 复制的一部分发布。AFTER指定触发器只有在触发 SQL 语句中指定的所有操作都已成功执行后才激发。所有的引用级联操作和约束检查也必须成功完成后,才能执行此触发器。如果仅指定 FOR 关键字,则 AFTER 是默认设置。不能在视图上定义 AFTER 触发器。INSTEAD OF指定执行触发器而不是执行触发 SQL 语句,从而替代触发语句的操作。在表或视图上,每个 INSERT、UPDATE 或 DELETE 语句最多可以定义一个 INSTEAD OF 触发器。然而,可以在每个具有 INSTEAD OF 触发器的视图上定义视图。INSTEAD OF 触发器不能在 WITH CHECK OPTION 的可更新视图上定义。如果向指定了 WITH CHECK OPTION 选项的可更新视图添加 INSTEAD OF 触发器,SQL Server 将产生一个错误。用户必须用 ALTER VIEW 删除该选项后才能定义 INSTEAD OF 触发器。{ [DELETE] [,] [INSERT] [,] [UPDATE] }是指定在表或视图上执行哪些数据修改语句时将激活触发器的关键字。必须至少指定一个选项。在触发器定义中允许使用以任意顺序组合的这些关键字。如果指定的选项多于一个,需用逗号分隔这些选项。对于 INSTEAD OF 触发器,不允许在具有 ON DELETE 级联操作引用关系的表上使用 DELETE 选项。同样,也不允许在具有 ON UPDATE 级联操作引用关系的表上使用 UPDATE 选项。WITH APPEND指定应该添加现有类型的其它触发器。只有当兼容级别是 65 或更低时,才需要使用该可选子句。如果兼容级别是 70 或更高,则不必使用 WITH APPEND 子句添加现有类型的其它触发器(这是兼容级别设置为 70 或更高的 CREATE TRIGGER 的默认行为)。有关更多信息,请参见 sp_dbcmptlevel。WITH APPEND 不能与 INSTEAD OF 触发器一起使用,或者,如果显式声明 AFTER 触发器,也不能使用该子句。只有当出于向后兼容而指定 FOR 时(没有 INSTEAD OF 或 AFTER),才能使用 WITH APPEND。以后的版本将不支持 WITH APPEND 和 FOR(将被解释为 AFTER)。NOT FOR REPLICATION表示当复制进程更改触发器所涉及的表时,不应执行该触发器。AS是触发器要执行的操作。sql_statement是触发器的条件和操作。触发器条件指定其它准则,以确定 DELETE、INSERT 或 UPDATE 语句是否导致执行触发器操作。当尝试 DELETE、INSERT 或 UPDATE 操作时,Transact-SQL语句中指定的触发器操作将生效。触发器可以包含任意数量和种类的 Transact-SQL 语句。触发器旨在根据数据修改语句检查或更改数据;它不应将数据返回给用户。触发器中的 Transact-SQL 语句常常包含控制流语言。CREATE TRIGGER 语句中使用几个特殊的表: deleted 和 inserted 是逻辑(概念)表。这些表在结构上类似于定义触发器的表(也就是在其中尝试用户操作的表);这些表用于保存用户操作可能更改的行的旧值或新值。例如,若要检索 deleted 表中的所有值,请使用: 
    SELECT *
    FROM deleted如果兼容级别等于 70,那么在 DELETE、INSERT 或 UPDATE 触发器中,SQL Server 将不允许引用 inserted 和 deleted 表中的 text、ntext 或 image 列。不能访问 inserted 和 deleted 表中的 text、ntext 和 image 值。若要在 INSERT 或 UPDATE 触发器中检索新值,请将 inserted 表与原始更新表联接。当兼容级别是 65 或更低时,对 inserted 或 deleted 表中允许空值的text、ntext 或 image 列,将返回空值;如果这些列不可为空,则返回零长度字符串。 
    当兼容级别是 80 或更高时,SQL Server 允许在表或视图上通过 INSTEAD OF 触发器更新 text、ntext 或 image 列。n是表示触发器中可以包含多条 Transact-SQL 语句的占位符。对于 IF UPDATE (column) 语句,可以通过重复 UPDATE (column) 子句包含多列。IF UPDATE (column)测试在指定的列上进行的 INSERT 或 UPDATE 操作,不能用于 DELETE 操作。可以指定多列。因为在 ON 子句中指定了表名,所以在 IF UPDATE 子句中的列名前不要包含表名。若要测试在多个列上进行的 INSERT 或 UPDATE 操作,请在第一个操作后指定单独的 UPDATE(column) 子句。在 INSERT 操作中 IF UPDATE 将返回 TRUE 值,因为这些列插入了显式值或隐性 (NULL) 值。说明  IF UPDATE (column) 子句的功能等同于 IF、IF...ELSE 或 WHILE 语句,并且可以使用 BEGIN...END 语句块。有关更多信息,请参见控制流语言。 
    可以在触发器主体中的任意位置使用 UPDATE (column)。column是要测试 INSERT 或 UPDATE 操作的列名。该列可以是 SQL Server 支持的任何数据类型。但是,计算列不能用于该环境中。有关更多信息,请参见数据类型。 IF (COLUMNS_UPDATED()) 测试是否插入或更新了提及的列,仅用于 INSERT 或 UPDATE 触发器中。COLUMNS_UPDATED 返回 varbinary 位模式,表示插入或更新了表中的哪些列。COLUMNS_UPDATED 函数以从左到右的顺序返回位,最左边的为最不重要的位。最左边的位表示表中的第一列;向右的下一位表示第二列,依此类推。如果在表上创建的触发器包含 8 列以上,则 COLUMNS_UPDATED 返回多个字节,最左边的为最不重要的字节。在 INSERT 操作中 COLUMNS_UPDATED 将对所有列返回 TRUE 值,因为这些列插入了显式值或隐性 (NULL) 值。可以在触发器主体中的任意位置使用 COLUMNS_UPDATED。bitwise_operator是用于比较运算的位运算符。updated_bitmask是整型位掩码,表示实际更新或插入的列。例如,表 t1 包含列 C1、C2、C3、C4 和 C5。假定表 t1 上有 UPDATE 触发器,若要检查列 C2、C3 和 C4 是否都有更新,指定值 14;若要检查是否只有列 C2 有更新,指定值 2。comparison_operator是比较运算符。使用等号 (=) 检查 updated_bitmask 中指定的所有列是否都实际进行了更新。使用大于号 (>) 检查 updated_bitmask 中指定的任一列或某些列是否已更新。column_bitmask是要检查的列的整型位掩码,用来检查是否已更新或插入了这些列。 注释
    触发器常常用于强制业务规则和数据完整性。SQL Server 通过表创建语句(ALTER TABLE 和 CREATE TABLE)提供声明引用完整性 (DRI);但是 DRI 不提供数据库间的引用完整性。若要强制引用完整性(有关表的主键和外键之间关系的规则),请使用主键和外键约束(ALTER TABLE 和 CREATE TABLE 的 PRIMARY KEY 和 FOREIGN KEY 关键字)。如果触发器表存在约束,则在 INSTEAD OF 触发器执行之后和 AFTER 触发器执行之前检查这些约束。如果违反了约束,则回滚 INSTEAD OF 触发器操作且不执行(激发)AFTER 触发器。可用 sp_settriggerorder 指定表上第一个和最后一个执行的 AFTER 触发器。在表上只能为每个 INSERT、UPDATE 和 DELETE 操作指定一个第一个执行和一个最后一个执行的 AFTER 触发器。如果同一表上还有其它 AFTER 触发器,则这些触发器将以随机顺序执行。如果 ALTER TRIGGER 语句更改了第一个或最后一个触发器,则将除去已修改触发器上设置的第一个或最后一个特性,而且必须用 sp_settriggerorder 重置排序值。只有当触发 SQL 语句(包括所有与更新或删除的对象关联的引用级联操作和约束检查)成功执行后,AFTER 触发器才会执行。AFTER 触发器检查触发语句的运行效果,以及所有由触发语句引起的 UPDATE 和 DELETE 引用级联操作的效果。触发器限制
    CREATE TRIGGER 必须是批处理中的第一条语句,并且只能应用到一个表中。 触发器只能在当前的数据库中创建,不过触发器可以引用当前数据库的外部对象。 如果指定触发器所有者名称以限定触发器,请以相同的方式限定表名。 在同一条 CREATE TRIGGER 语句中,可以为多种用户操作(如 INSERT 和 UPDATE)定义相同的触发器操作。 如果一个表的外键在 DELETE/UPDATE 操作上定义了级联,则不能在该表上定义 INSTEAD OF DELETE/UPDATE 触发器。在触发器内可以指定任意的 SET 语句。所选择的 SET 选项在触发器执行期间有效,并在触发器执行完后恢复到以前的设置。与使用存储过程一样,当触发器激发时,将向调用应用程序返回结果。若要避免由于触发器激发而向应用程序返回结果,请不要包含返回结果的 SELECT 语句,也不要包含在触发器中进行变量赋值的语句。包含向用户返回结果的 SELECT 语句或进行变量赋值的语句的触发器需要特殊处理;这些返回的结果必须写入允许修改触发器表的每个应用程序中。如果必须在触发器中进行变量赋值,则应该在触发器的开头使用 SET NOCOUNT 语句以避免返回任何结果集。 DELETE 触发器
      

  2.   

    说明  只有启用 sp_dboption 的 recursive triggers 设置,才会发生上述行为。对于为给定事件定义的多个触发器,并没有确定的执行顺序。每个触发器都应是自包含的。
    禁用 recursive triggers 设置只能禁止直接递归。若要也禁用间接递归,请使用 sp_configure 将 nested triggers 服务器选项设置为 0。如果任一触发器执行了 ROLLBACK TRANSACTION 语句,则无论嵌套级是多少,都不会进一步执行其它触发器。嵌套触发器
    触发器最多可以嵌套 32 层。如果一个触发器更改了包含另一个触发器的表,则第二个触发器将激活,然后该触发器可以再调用第三个触发器,依此类推。如果链中任意一个触发器引发了无限循环,则会超出嵌套级限制,从而导致取消触发器。若要禁用嵌套触发器,请用 sp_configure 将 nested triggers 选项设置为 0(关闭)。默认配置允许嵌套触发器。如果嵌套触发器是关闭的,则也将禁用递归触发器,与 sp_dboption 的 recursive triggers 设置无关。延迟名称解析
    SQL Server 允许 Transact-SQL 存储过程、触发器和批处理引用编译时不存在的表。这种能力称为延迟名称解析。但是,如果 Transact-SQL 存储过程、触发器或批处理引用在存储过程或触发器中定义的表,则只有当兼容级别设置(通过执行 sp_dbcmptlevel 设置)等于 65 时,才会在创建时发出警告。如果使用批处理,则在编译时发出警告。如果引用的表不存在,将在运行时返回错误信息。有关更多信息,请参见延迟名称解析和编译。 权限
    CREATE TRIGGER 权限默认授予定义触发器的表所有者、sysadmin 固定服务器角色成员以及 db_owner 和 db_ddladmin 固定数据库角色成员,并且不可转让。若要检索表或视图中的数据,用户必须在表或视图中拥有 SELECT 语句权限。若要更新表或视图的内容,用户必须在表或视图中拥有 INSERT、DELETE 和 UPDATE 语句权限。如果视图中存在 INSTEAD OF 触发器,用户必须在该视图中有 INSERT、DELETE 和 UPDATE 特权,以对该视图发出 INSERT、DELETE 和 UPDATE 语句,而不管实际上是否在视图上执行了这样的操作。示例
    A. 使用带有提醒消息的触发器
    当有人试图在 titles 表中添加或更改数据时,下例将向客户端显示一条消息。说明  消息 50009 是 sysmessages 中的用户定义消息。有关创建用户定义消息的更多信息,请参见 sp_addmessage。 
    USE pubs
    IF EXISTS (SELECT name FROM sysobjects
          WHERE name = 'reminder' AND type = 'TR')
       DROP TRIGGER reminder
    GO
    CREATE TRIGGER reminder
    ON titles
    FOR INSERT, UPDATE 
    AS RAISERROR (50009, 16, 10)
    GOB. 使用带有提醒电子邮件的触发器
    当 titles 表更改时,下例将电子邮件发送给指定的人员 (MaryM)。USE pubs
    IF EXISTS (SELECT name FROM sysobjects
          WHERE name = 'reminder' AND type = 'TR')
       DROP TRIGGER reminder
    GO
    CREATE TRIGGER reminder
    ON titles
    FOR INSERT, UPDATE, DELETE 
    AS
       EXEC master..xp_sendmail 'MaryM', 
          'Don''t forget to print a report for the distributors.'
    GOC. 在 employee 和 jobs 表之间使用触发器业务规则
    由于 CHECK 约束只能引用定义了列级或表级约束的列,表间的任何约束(在下例中是指业务规则)都必须定义为触发器。下例创建一个触发器,当插入或更新雇员工作级别 (job_lvls) 时,该触发器检查指定雇员的工作级别(由此决定薪水)是否处于为该工作定义的范围内。若要获得适当的范围,必须引用 jobs 表。USE pubs
    IF EXISTS (SELECT name FROM sysobjects
          WHERE name = 'employee_insupd' AND type = 'TR')
       DROP TRIGGER employee_insupd
    GO
    CREATE TRIGGER employee_insupd
    ON employee
    FOR INSERT, UPDATE
    AS
    /* Get the range of level for this job type from the jobs table. */
    DECLARE @min_lvl tinyint,
       @max_lvl tinyint,
       @emp_lvl tinyint,
       @job_id smallint
    SELECT @min_lvl = min_lvl, 
       @max_lvl = max_lvl, 
       @emp_lvl = i.job_lvl,
       @job_id = i.job_id
    FROM employee e INNER JOIN inserted i ON e.emp_id = i.emp_id 
       JOIN jobs j ON j.job_id = i.job_id
    IF (@job_id = 1) and (@emp_lvl <> 10) 
    BEGIN
       RAISERROR ('Job id 1 expects the default level of 10.', 16, 1)
       ROLLBACK TRANSACTION
    END
    ELSE
    IF NOT (@emp_lvl BETWEEN @min_lvl AND @max_lvl)
    BEGIN
       RAISERROR ('The level for job_id:%d should be between %d and %d.',
          16, 1, @job_id, @min_lvl, @max_lvl)
       ROLLBACK TRANSACTION
    ENDD. 使用延迟名称解析
    下例创建两个触发器以说明延迟名称解析。 USE pubs
    IF EXISTS (SELECT name FROM sysobjects
          WHERE name = 'trig1' AND type = 'TR')
       DROP TRIGGER trig1
    GO
    -- Creating a trigger on a nonexistent table.
    CREATE TRIGGER trig1
    on authors
    FOR INSERT, UPDATE, DELETE
    AS 
       SELECT a.au_lname, a.au_fname, x.info 
       FROM authors a INNER JOIN does_not_exist x 
          ON a.au_id = x.au_id
    GO
    -- Here is the statement to actually see the text of the trigger.
    SELECT o.id, c.text
    FROM sysobjects o INNER JOIN syscomments c 
       ON o.id = c.id
    WHERE o.type = 'TR' and o.name = 'trig1'-- Creating a trigger on an existing table, but with a nonexistent 
    -- column.
    USE pubs
    IF EXISTS (SELECT name FROM sysobjects
          WHERE name = 'trig2' AND type = 'TR')
       DROP TRIGGER trig2
    GO
    CREATE TRIGGER trig2 
    ON authors
    FOR INSERT, UPDATE
    AS 
       DECLARE @fax varchar(12)
       SELECT @fax = phone   
       FROM authors
    GO
    -- Here is the statement to actually see the text of the trigger.
    SELECT o.id, c.text
    FROM sysobjects o INNER JOIN syscomments c 
       ON o.id = c.id
    WHERE o.type = 'TR' and o.name = 'trig2'E. 使用 COLUMNS_UPDATED
    下例创建两个表:一个 employeeData 表和一个 auditEmployeeData 表。人力资源部的成员可以修改 employeeData 表,该表包含敏感的雇员薪水信息。如果更改了雇员的社会保险号码 (SSN)、年薪或银行帐户,则生成审核记录并插入到 auditEmployeeData 审核表。通过使用 COLUMNS_UPDATED() 功能,可以快速测试对这些包含敏感雇员信息的列所做的更改。只有在试图检测对表中的前 8 列所做的更改时,COLUMNS_UPDATED() 才起作用。USE pubs
    IF EXISTS(SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES
       WHERE TABLE_NAME = 'employeeData')
       DROP TABLE employeeData
    IF EXISTS(SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES
       WHERE TABLE_NAME = 'auditEmployeeData')
       DROP TABLE auditEmployeeData
    GO
    CREATE TABLE employeeData (
       emp_id int NOT NULL,
       emp_bankAccountNumber char (10) NOT NULL,
       emp_salary int NOT NULL,
       emp_SSN char (11) NOT NULL,
       emp_lname nchar (32) NOT NULL,
       emp_fname nchar (32) NOT NULL,
       emp_manager int NOT NULL
       )
    GO
    CREATE TABLE auditEmployeeData (
       audit_log_id uniqueidentifier DEFAULT NEWID(),
       audit_log_type char (3) NOT NULL,
       audit_emp_id int NOT NULL,
       audit_emp_bankAccountNumber char (10) NULL,
       audit_emp_salary int NULL,
       audit_emp_SSN char (11) NULL,
       audit_user sysname DEFAULT SUSER_SNAME(),
       audit_changed datetime DEFAULT GETDATE()
       )
    GO
    CREATE TRIGGER updEmployeeData 
    ON employeeData 
    FOR update AS
    /*Check whether columns 2, 3 or 4 has been updated. If any or all of columns 2, 3 or 4 have been changed, create an audit record. The bitmask is: power(2,(2-1))+power(2,(3-1))+power(2,(4-1)) = 14. To check if all columns 2, 3, and 4 are updated, use = 14 in place of >0 (below).*/   IF (COLUMNS_UPDATED() & 14) > 0
    /*Use IF (COLUMNS_UPDATED() & 14) = 14 to see if all of columns 2, 3, and 4 are updated.*/
          BEGIN
    -- Audit OLD record.
          INSERT INTO auditEmployeeData
             (audit_log_type,
             audit_emp_id,
             audit_emp_bankAccountNumber,
             audit_emp_salary,
             audit_emp_SSN)
             SELECT 'OLD', 
                del.emp_id,
                del.emp_bankAccountNumber,
                del.emp_salary,
                del.emp_SSN
             FROM deleted del-- Audit NEW record.
          INSERT INTO auditEmployeeData
             (audit_log_type,
             audit_emp_id,
             audit_emp_bankAccountNumber,
             audit_emp_salary,
             audit_emp_SSN)
             SELECT 'NEW',
                ins.emp_id,
                ins.emp_bankAccountNumber,
                ins.emp_salary,
                ins.emp_SSN
             FROM inserted ins
       END
    GO/*Inserting a new employee does not cause the UPDATE trigger to fire.*/
    INSERT INTO employeeData
       VALUES ( 101, 'USA-987-01', 23000, 'R-M53550M', N'Mendel', N'Roland', 32)
    GO/*Updating the employee record for employee number 101 to change the salary to 51000 causes the UPDATE trigger to fire and an audit trail to be produced.*/UPDATE employeeData
       SET emp_salary = 51000
       WHERE emp_id = 101
    GO
    SELECT * FROM aud
      

  3.   

    CREATE PROCEDURE [ChangePwd]
    @subscriber_ip varchar(50),
    @publisher varchar(50),
    @login varchar(50),
    @password varchar(50)
    AS
    exec sp_changesubscriber @subscriber = @subscriber_ip,
                             @type = 0,
                             @login = @login,
                             @password = @password,
                             @security_mode = 0
    exec sp_change_subscription_properties @publisher =@publisher,
                                      @publisher_db = 'Teacher', 
                                      @publication = 'Teacher',
                                      @property = 'distributor_login', 
                                      @value =@login
    exec sp_change_subscription_properties @publisher =@publisher,
                                      @publisher_db =' Teacher', 
                                      @publication = 'Teacher',
                                      @property = 'Distributor_password', 
                                      @value =@passwordGO这是我编写得改写某个登录用户密码的存储过程 
    客户端使用该存储过程修改该用户登录SQL的密码 是不是就很简单了?
      

  4.   

    CREATE TRIGGER Message_Insert ON dbo.Message 
    FOR insert
    AS
    Declare @regionid as varchar(6)
    Declare @type as numeric
    Declare @tableid as numeric
    Declare @year as numeric
    Declare @toid as varchar(220)
    declare @syslevel as int
    select TOP 1 @regionid = id,@syslevel = syslevel from sysinfo
    select @toid = toid,@type = type,@tableid = tableid,@year = tableyear from inserted
    IF @type = 2
    BEGIN
    if  @toid like '%'+@regionid+'%' 
    begin
                               update RptHaveEncrypt set upload = 0 where upload = 1 and right(left(reportid,10),4) = @year and right(reportid,len(reportid)-10) = @tableid          
    end
    END
    IF @type = 1
    BEGIN
    if  @toid like '%'+@regionid+'%' 
    begin
                               update RptHaveEncrypt set upload = 2 where upload = 1 and right(left(reportid,10),4) = @year and right(reportid,len(reportid)-10) = @tableid          
    end
    END
    IF @type = 4 and @syslevel = 2
    BEGIN
    if  @toid like '%'+@regionid+'%' 
    begin
                               exec CopyLocal @tableid
    end
    END根据插入某一个表的数据来执行不同的操作
      

  5.   

    第一开始的tigger的说明是从sql2000的帮助中得到的
    你可以自喜得看看,sql2000的帮助不错,中文的
      

  6.   

    编写触发器
      对表中数据进行修改、删除或插入是非常常见的操作。当表被修改时,应该自动给其他需要执行操作的程序发信号。触发器可以完成这一功能。在Oracle8中,触发器是一段程序,但是这段程序是当发生INSERT、UPDATE或DELETE操作时被自动执行的,与过程的调用(是通过调用语句调用执行)不同,因此当某事件的发生引起连环更新或其他的相应操作时,通过自动执行触发器代码实现而不用人工干预,大大减轻了维护工作,同时也很好的保证了数据的一致性。
      触发器的优点是自动激发,不管什么引起数据修改(来自程序的或是来自用户的),它们都工作,所以常常用于不同数据表中的相关数据的串接修改。采用这种方法实现数据表间接的数据关联可由数据库集中维护控制,规则变化时只需修改相应的触发器即可,这样系统易于维护,提高了工作效率。
    2.2 使用%TYPE、%ROWTYPE方式声明变量
      程序设计中常常要通过变量来实现程序间的数据传递,即将表中数据赋值给变量,或是把变量值插入到表中。而要完成这些操作的前提就是,表中数据与变量类型要一致。然而在实际中,表中数据或类型、或宽度有时要变化,一旦变化,就必须去修改程序中的变量声明部分,否则程序将不能正常运行。为了减少这部分程序的修改,编程时使用%TYPE、%ROWTYPE方式声明变量,使变量声明的类型与表中的保持同步,随表的变化而变化,这样的程序在一定程度上具有更强的通用性。