zoukankan      html  css  js  c++  java
  • SQLServer 触发器 同时插入多条记录有关问题

    由于 SQL Server 的触发器, 没有 FOR EACH ROW (ORACL中有)的选项, 有时候不正确的使用 inserted 与deleted 可能会有点麻烦。

    下面来一个简单的例子

    --假设这个A是主表

    CREATE TABLE A(
      AID INT IDENTITY(1, 1) PRIMARY KEY,
      money INT
    );

    -- 假设这个B是 日志表, 负责记录 A表 发生的变化。
    CREATE TABLE B(
      BID INT IDENTITY(1, 1) PRIMARY KEY,

      AID INT,
      money INT
    );
    go

    -- 假设这个C也是日志表, 负责记录 A表 发生的变化。

    -- 但是这个C表是用于演示 不正确使用的例子。

    CREATE TABLE C(
      CID INT IDENTITY(1, 1) PRIMARY KEY,
      AID INT,
      money INT
    );
    go

    -- 测试的存储过程

    -- 当 A 表 插入 / 更新 / 删除的时候i, 都触发。

    CREATE TRIGGER AfterA
    ON A
    FOR INSERT,UPDATE,DELETE
    AS
      DECLARE @aid INT, @money INT;
    BEGIN
      IF EXISTS(SELECT 1 FROM inserted) AND NOT EXISTS(SELECT 1 FROM deleted)
      BEGIN
        -- 插入触发.
        -- 正确的使用.
        INSERT INTO B
        SELECT
          inserted.aid,
          inserted.money
        FROM
          inserted;


        -- 不正确的使用.  如果一次性插入多条记录时, inserted是一个表, 用以下的语句 就只会取一条记录了
        SELECT @aid = aid, @money = money FROM inserted;
        INSERT INTO C VALUES ( @aid, @money);
      END;
      IF EXISTS(SELECT 1 FROM inserted) AND EXISTS(SELECT 1 FROM deleted)
      BEGIN
        -- 更新触发.
        -- 正确的使用.
        INSERT INTO B
        SELECT
          inserted.aid,
          inserted.money - deleted.money
        FROM
          inserted, deleted
        WHERE
          inserted.AID = deleted.AID;
        -- 不正确的使用.
        SELECT @aid = aid, @money = money FROM inserted;
        SELECT @money = @money - money FROM deleted;
        INSERT INTO C VALUES ( @aid, @money);
      END;
      IF NOT EXISTS(SELECT 1 FROM inserted) AND EXISTS(SELECT 1 FROM deleted)
      BEGIN
        -- 删除触发
        -- 正确的使用.
        INSERT INTO B
        SELECT
          deleted.aid,
          0 - deleted.money
        FROM
          deleted;
        -- 不正确的使用.
        SELECT @aid = aid, @money = 0 - money FROM deleted;
        INSERT INTO C VALUES ( @aid, @money);
      END;
    END;
    go
    -- 一条SQL语句,插入一条数据
    INSERT INTO A VALUES (100);
    -- 一条SQL语句,插入多条数据 (触发器只会执行一次)
    INSERT INTO A
      SELECT 10
      UNION ALL SELECT 20;  
    GO

    -- 一条SQL语句,更新一条数据
    UPDATE A SET money = money - 50 WHERE AID = 1;
    -- 一条SQL语句,更新多条数据
    UPDATE A SET money = money + 50 WHERE AID != 1;
    GO

    -- 一条SQL语句,删除一条数据
    DELETE FROM A WHERE AID = 1;
    -- 一条SQL语句,删除多条数据
    DELETE FROM A WHERE AID != 1;
    GO

    SELECT * FROM B
    GO
    BID         AID         money
    ----------- ----------- -----------
              1           1         100
              2           3          20
              3           2          10

              4           1         -50
              5           3          50
              6           2          50

              7           1         -50
              8           3         -70
              9           2         -60

    (9 行受影响)

    SELECT * FROM C
    go
    CID         AID         money
    ----------- ----------- -----------
              1           1         100
              2           2          10
              3           1         -50
              4           2          30
              5           1         -50
              6           2         -60

    (6 行受影响)

    这里, AID = 3 的数据,没有被触发器处理。

    在SQL Server的触发器当中。如果简单的

    SELECT @aid = aid, @money = money FROM inserted;

    那么,当 SQL 语句是同时更新多条记录的时候, 就会有后面的数据,没有被触发器处理掉。

    引用: http://hi.baidu.com/wangzhiqing999/item/618388d8e5f68959d73aae26

    资料: http://database.ccidnet.com/art/1105/20070726/1156675_1.html

  • 相关阅读:
    多线程编程学习笔记——任务并行库(三)
    多线程编程学习笔记——任务并行库(二)
    多线程编程学习笔记——任务并行库(一)
    多线程编程学习笔记——线程池(三)
    多线程编程学习笔记——线程池(二)
    多线程编程学习笔记——线程池(一)
    多线程编程学习笔记——线程同步(三)
    多线程编程学习笔记——线程同步(二)
    多线程编程学习笔记——线程同步(一)
    多线程编程学习笔记-基础(三)
  • 原文地址:https://www.cnblogs.com/chencidi/p/3357284.html
Copyright © 2011-2022 走看看