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
SQLServer 触发器 同时插入多条记录有关问题的更多相关文章
- AX 插入一条记录提示表记录已经存在,但是该记录实际上是不存在的。
做测试的时候遇到一个情况"AX 插入一条记录提示表记录已经存在,但是该记录实际上是不存在的." 检查到该表(TABLE_ABC)所有的key都是AllowDuplicate的, 继 ...
- 一次插入多条记录 [mysql]
调用多次INSERT语句不就可以插入多条记录了吗?但使用这种方法要增加服务器的负荷,因为,执行每一次SQL服务器都要同样对SQL进行分析.优化等操作.幸好MySQL提供了另一种解决方案,就是使用一条I ...
- 无废话Android之listview入门,自定义的数据适配器、采用layoutInflater打气筒创建一个view对象、常用数据适配器ArrayAdapter、SimpleAdapter、使用ContentProvider(内容提供者)共享数据、短信的备份、插入一条记录到系统短信应用(3)
1.listview入门,自定义的数据适配器 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/and ...
- sql 中实现往表中插入一条记录并返回当前记录的ID
写一条存储过程,实现往User中插入一条记录并返回当前UserId(自增长id) --推荐写法 if(Exists(select * from sys.objects where name=N'Usp ...
- ACCESS-delphi向中插入一条记录报错,但ACCESS不会
问题:在DELPHI中向ACCESS中插入一条记录时,提示“插入错误”,但是取出SQL直接放在ACCESS中插入成功?答:原因是插入语句中的字段名是DELPHI的内部标示符.
- 一条insert语句批量插入多条记录
一条insert语句批量插入多条记录 常见的insert语句,向数据库中,一条语句只能插入一条数据: insert into persons (id_p, lastname , firstName, ...
- mysql中插入多条记录-微软批处理
当向mysql中插入大量数据时,可以使用微软的批处理方式.这样可以防止内存溢出又提高了效率.我写了一个mysql中插入多条记录的例子.赋值代码可以直接使用. 1.首先需要添加两个dll MySql.D ...
- SQLServer 分组查询相邻两条记录的时间差
原文:SQLServer 分组查询相邻两条记录的时间差 首先,我们通过数据库中表的两条记录来引出问题,如下图 以上为一个记录操作记录的表数据.OrderID为自增长列,后面依次为操作类型,操作时间,操 ...
- mySQL中插入多条记录
用一条INSERT向SQL中插入多条记录 2008-12-22 10:07:01| 分类: 记事本_编程技术|举报|字号 订阅 Sql 语法: 插入多行记录 Insert Into Tabl ...
随机推荐
- JS学习第四课
当我们删除某列表格,再添加新的一列时,它的序号该如何控制呢.这里id=oTab.tBodies[0].rows.length+1 otd.innerHTML=id++; 很关键哦. ...
- [Guava学习笔记]Strings: 字符串处理
我的技术博客经常被流氓网站恶意爬取转载.请移步原文:http://www.cnblogs.com/hamhog/p/3861502.html,享受整齐的排版.有效的链接.正确的代码缩进.更好的阅读体验 ...
- ADO.NET笔记——存储二进制大对象(BLOB)
相关知识 上传二进制大对象(Binary Large Object)(如图片.视频等)的基本编程步骤是: 在数据库中使用varbinary(MAX).varchar(MAX)或者nvarchar(MA ...
- WP开发笔记——去除 HTML 标签
获取到一段HTML类型的信息,显示在WP的webbrowser控件中,如果不加处理的话,会显示出各种神烦的HTML标签. 这时,需要我们将这HTML类型的信息进行处理去除HTML标签后再显示出来,这里 ...
- file与 byte[] 互转
byte 转file String filepath="D:\\"+getName(); File file=new File(filepath); ...
- HTML5读取本地文件 FileReader API接口
1.FileReader接口的方法 FileReader接口有4个方法,其中3个用来读取文件,另一个用来中断读取.无论读取成功或失败,方法并不会返回读取结果,这一结果存储在result属性中. Fil ...
- keditor_php图片上传
<script type="text/javascript" src="/statics/js/kindeditor/kindeditor-min.js" ...
- Global::pickSpecificClass_DNT
/*************************************************** Created Date: 13 Jul 2013 Created By: Jimmy Xie ...
- nginx+keepalived双主高可用负载均衡
实验环境及软件版本:CentOS版本: 6.6(2.6.32.-504.el6.x86_64)nginx版本: nginx-1.6.3keepalived版本:keepalived-1.2.7 主LB ...
- Python中docstring文档的写法
该写法根据Python的PEP 257文档总结. 类的函数称为方法(method),模块里的函数称为函数(function) 每一个包,模块,类,函数,方法都应该包含文档,包括类的__init__方法 ...