由于 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

SQLServer 触发器 同时插入多条记录有关问题的更多相关文章

  1. AX 插入一条记录提示表记录已经存在,但是该记录实际上是不存在的。

    做测试的时候遇到一个情况"AX 插入一条记录提示表记录已经存在,但是该记录实际上是不存在的." 检查到该表(TABLE_ABC)所有的key都是AllowDuplicate的, 继 ...

  2. 一次插入多条记录 [mysql]

    调用多次INSERT语句不就可以插入多条记录了吗?但使用这种方法要增加服务器的负荷,因为,执行每一次SQL服务器都要同样对SQL进行分析.优化等操作.幸好MySQL提供了另一种解决方案,就是使用一条I ...

  3. 无废话Android之listview入门,自定义的数据适配器、采用layoutInflater打气筒创建一个view对象、常用数据适配器ArrayAdapter、SimpleAdapter、使用ContentProvider(内容提供者)共享数据、短信的备份、插入一条记录到系统短信应用(3)

    1.listview入门,自定义的数据适配器 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/and ...

  4. sql 中实现往表中插入一条记录并返回当前记录的ID

    写一条存储过程,实现往User中插入一条记录并返回当前UserId(自增长id) --推荐写法 if(Exists(select * from sys.objects where name=N'Usp ...

  5. ACCESS-delphi向中插入一条记录报错,但ACCESS不会

    问题:在DELPHI中向ACCESS中插入一条记录时,提示“插入错误”,但是取出SQL直接放在ACCESS中插入成功?答:原因是插入语句中的字段名是DELPHI的内部标示符.

  6. 一条insert语句批量插入多条记录

    一条insert语句批量插入多条记录 常见的insert语句,向数据库中,一条语句只能插入一条数据: insert into persons (id_p, lastname , firstName,  ...

  7. mysql中插入多条记录-微软批处理

    当向mysql中插入大量数据时,可以使用微软的批处理方式.这样可以防止内存溢出又提高了效率.我写了一个mysql中插入多条记录的例子.赋值代码可以直接使用. 1.首先需要添加两个dll MySql.D ...

  8. SQLServer 分组查询相邻两条记录的时间差

    原文:SQLServer 分组查询相邻两条记录的时间差 首先,我们通过数据库中表的两条记录来引出问题,如下图 以上为一个记录操作记录的表数据.OrderID为自增长列,后面依次为操作类型,操作时间,操 ...

  9. mySQL中插入多条记录

    用一条INSERT向SQL中插入多条记录 2008-12-22 10:07:01|  分类: 记事本_编程技术|举报|字号 订阅     Sql 语法: 插入多行记录 Insert Into Tabl ...

随机推荐

  1. Swift 概述及Swift运算符和表达式

    Swift  是用于设计 iOS 及 Mac OS X 应用的一门新 语言. Swift 特点 •   Swift  保留了 C  与 Objective-C 的优点,并摒弃 其为了兼容 C  语言所 ...

  2. .net framework缓存遍历

    背景: 公司的老框架里的登录信息用的MemoryCache保存的,为了实现单用户登录(即一个账号不能同事登录),需要在登录前对已经登录的信息做遍历. 大致思路如下: 本方法可用于清除所有的缓存. 1. ...

  3. 洛谷 P3368 【模板】树状数组 2

    题目描述 如题,已知一个数列,你需要进行下面两种操作: 1.将某区间每一个数数加上x 2.求出某一个数的和 输入输出格式 输入格式: 第一行包含两个整数N.M,分别表示该数列数字的个数和操作的总个数. ...

  4. C# 枚举操作扩展类

    using System; using System.Linq; using System.ComponentModel; namespace Demo.Common { /// <summar ...

  5. NSS_07 extjs中grid在工具条上的查询

    碰到的每个问题, 我都会记下走过的弯路,尽量回忆白天的开发过程, 尽量完整, 以使自己以后可以避开这些弯路. 这个问题在系统中应用得比较多, 在一个gridpanel的工具条上有俩搜索框, panel ...

  6. php读取html并截取字符串

    一般php采集代码能用的到,这里只是简单的实现代码. <?php $title='脚本学堂'; $hello='jbxue.com!'; $file=file_get_contents('htt ...

  7. PHP获取上个月、下个月、本月的日期(strtotime(),date())

    今天写程序的时候,突然发现了很早以前写的获取月份天数的函数,经典的switch版,但是获得上月天数的时候,我只是把月份-1了,估计当时太困了吧,再看到有种毛骨悚然的感觉,本来是想再处理一下的,但是一想 ...

  8. 不再用.NET框架

    .NET 平台很棒.真的很棒.直到它不再那么棒.我为什么不再用 .NET?简单来说,它限制了我们选择的能力(对我来说很重要),转移了我们的注意力,使得我们向内认知它的安全性,替代了帮助我们认知外面广阔 ...

  9. Android之“Unfortunately,xxx has stopped!”

    初学Android遇到Unfortunately,xxx has stopped!真是一件让人头疼的事情,下面就遇到的两种可能情况给出解决方案.通常遇到的情况在于由一个Activity跳转至另一个Ac ...

  10. ref 和out的用法以及区别

    在项目其实很少用ref和out,但是我们常用的工具resharep在帮我们重构的时候难免会给我们重构成带有ref或者是out的方法. 本人也是用的少所以难免忘记,留下简略笔记,以供后来自我参考: 为何 ...