zoukankan      html  css  js  c++  java
  • sql trigger

    定义

    在SQL Server里面也就是对某一个表的一定的操作,触发某种条件,从而执行的一段程序。触发器是一个特殊的存储过程。

    常见的触发器有三种:分别应用于Insert , Update , Delete 事件。

    我们为什么要使用触发器, 比如:

    1.当我们修改了一张表, 需要在日志中记录一下,这样就需要用到触发器(不知道大家是不是用的其他方法)

    2.虚拟采购表和库存表, 当采购表inert了一条数据, 相应的要在库存表中update或insert一条数据

    3.虚拟销售表和库存表, 当销售表inert了一条数据, 相应的要在库存表中update一条数据

    例1

    create trigger myTrigger --创建触发器
    on tb--触发源
    for updateas --触发操作
    insert into Sys_Log values (........)--触发结果
     

    触发器语句中使用了两种特殊的表:deleted 表和 inserted 表。

    Deleted 表用于存储 DELETE 和 UPDATE 语句所影响的行的复本。在执行 DELETE 或 UPDATE 语句时,行从触发器表中删除,并传输到 deleted 表中。Deleted 表和触发器表通常没有相同的行。

    Inserted 表用于存储 INSERT 和 UPDATE 语句所影响的行的副本。在一个插入或更新事务处理中,新建行被同时添加到 inserted 表和触发器表中。Inserted 表中的行是触发器表中新行的副本。

    1.插入操作(Insert)

    Inserted表有数据,Deleted表无数据

    2.删除操作(Delete)

    Inserted表无数据,Deleted表有数据

    3.更新操作(Update)

    Inserted表有数据(新数据),Deleted表有数据(旧数据)

     

    例2

    CREATE TRIGGER T_INSERT_卷烟销售表 
    ON 卷烟销售表 
    FOR INSERT 
    AS 
    BEGIN TRANSACTION 
    ------------------------------------------------------
    --检查数据的合法性:销售的卷烟是否有库存,或者库存是否大于零 
    IF NOT EXISTS ( 
    SELECT 库存数量 
    FROM 卷烟库存表 
    WHERE 卷烟品牌 IN (SELECT 卷烟品牌 FROM INSERTED) 
    ) 
    BEGIN 
    --返回错误提示 
    RAISERROR(’错误!该卷烟不存在库存,不能销售。’,16,1) 
    --回滚事务 
    ROLLBACK 
    RETURN 
    END 
    ------------------------------------------------------
    IF EXISTS ( 
    SELECT 库存数量 
    FROM 卷烟库存表 
    WHERE 卷烟品牌 IN (SELECT 卷烟品牌 FROM INSERTED) AND 
    库存数量 <= 0 
    ) 
    BEGIN 
    --返回错误提示 
    RAISERROR(’错误!该卷烟库存小于等于0,不能销售。’,16,1) 
    --回滚事务 
    ROLLBACK 
    RETURN 
    END 
     
     
    -------------对合法的数据进行处理 --------------------
     
    --强制执行下列语句,保证业务规则 
    UPDATE 卷烟销售表 
    SET 销售金额 = 销售数量 * 销售单价 
    WHERE 卷烟品牌 IN (SELECT 卷烟品牌 FROM INSERTED) 
     
    DECLARE @卷烟品牌 VARCHAR(40) 
    SET @卷烟品牌 = (SELECT 卷烟品牌 FROM INSERTED) 
     
    DECLARE @销售数量 MONEY 
    SET @销售数量 = (SELECT 销售数量 FROM INSERTED) 
     
    UPDATE 卷烟库存表 
    SET 库存数量 = 库存数量 - @销售数量, 
    库存金额 = (库存数量 - @销售数量)*库存单价 
    WHERE 卷烟品牌 = @卷烟品牌 
    COMMIT TRANSACTION 
    GO 

    补充:

    1、本示例主要通过一个简单的业务规则实现来进行触发器使用的说明,具体的要根据需要灵活处理;

    2、关于触发器要理解并运用好 INSERTED ,DELETED 两个系统表;

    3、本示例创建的触发器都是 FOR INSERT ,具体的语法可参考:

    Trigger语法

    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 ] 
    } 
    } 

    ☑ if update (col_name):表明所作的操作对指定列是否有影响,有影响,则激活触发器。此外,因为delete 操作只对行有影响, 所以如果使用delete操作就不能用这条语句了(虽然使用也不出错,但是不能激活触发器,没意义)。

    ☑ 触发器执行时用到的两个特殊表:deleted ,inserted deleted 和inserted 可以说是一种特殊的临时表,是在进行激活触发器时由系统自动生成的,其结构与触发器作用的表结构是一

    样的,只是存放 的数据有差异。

    在sql触发器中如何获得被修改行的ID

    这个在上面的例2中已经有所提及

    create trigger TgName
    on tb
    for update
    as
    if update(recommend)
    begin
    update tb set commenddate=(getdate()) from tb inner join inserted on tb.vlistid=Inserted.vlistid
    end

    关键在于Inserted


    触发器貌似代替了之前我在BLL写事务来处理原子性操作的代码, 应该是一种简化.

    更详细内容参看http://wenku.baidu.com/view/3b3fb53343323968011c92ce.html

  • 相关阅读:
    04_web基础(六)之请求转发与重定向
    04_web基础(五)之cookie与session
    04_web基础(四)之servlet详解
    04_web基础(三)之进一步理解web
    04_web基础(二)之web构建
    本地密码提取工具-LAZAGNE
    免杀工具汇总
    流量取证-提取文件
    CA证书安装以及sslh协议转发
    ssh 端口转发
  • 原文地址:https://www.cnblogs.com/TivonStone/p/2362686.html
Copyright © 2011-2022 走看看