在论坛中出现的比较难的sql问题:20(触发器专题2)
触发器继续执行 ROLLBACK 语句之后的所有其余语句。 如果这些语句中的任意语句修改数据,则不回滚这些修改。 执行其余的语句不会激发嵌套触发器。
其中“执行其余的语句不会激发嵌套触发器”,是否意味着在回滚操作后面的语句如果继续执行的话,后面语句触发的触发器就不会执行了。比如后面的语句有针对一个表的update操作,而这张表又有update的触发器,这个时候update会执行成功,但触发器不会执行?
从下面的insert时的输出,可以看出,在触发器中rollback之后的语句,是可以执行的,另外,update另一个表的操作也执行成功,并且触发了触发器。
--drop table t1 --drop table t2 create table t1(id int) create table t2(id int) insert into t2 values(100) go create trigger dbo.trigger_t1 on t1 for insert as rollback; select '这是rollback之后的语句,这里能执行' update t2 set id = 1; go create trigger dbo.trigger_t2 on t2 for update as select '这是t2的update触发器,这里能执行' go --插入数据 insert into t1 values(1) /* 这是rollback之后的语句,这里能执行 这是t2的update触发器,这里能执行 消息 3609,级别 16,状态 1,第 3 行 事务在触发器中结束。批处理已中止。 */ --没有记录 select * from t1 select * from t2 /* id 1 */
我在A表写了个触发器 插入后执行,是向B表插入一条记录
USE [test]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER TRIGGER [dbo].[tba_delete]
ON [dbo].[tba]
AFTER INSERT
AS
BEGIN
SET NOCOUNT ON;
insert into test.dbo.tbb(title,info) values('title','info');
END
在A表插入数据后正常。当我把 语言改为:
insert into test.dbo.tbb(id,title,info) values(1,'title','info');
故意出错。问题出现了,当触发器内的语句出错,向A表插入的数据就不能成功插入。
向朋友们求教个问题。我要如何把触发器中的出错信息记录下来?或者在什么地方可以查看到触发器执行时是否出错了,及查看错误的信息?
USE [test]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
create table [tba](title varchar(20),info varchar(20))
create table tbb(title varchar(20),info varchar(20))
--创建一个存放错误信息的表
create table tb_error_message
(
obj_name nvarchar(30),
obj_type nvarchar(15),
err_msg nvarchar(100),
err_date datetime
)
go
drop trigger tba_delete
go
create TRIGGER [dbo].[tba_delete]
ON [dbo].[tba]
AFTER INSERT
AS
BEGIN
SET NOCOUNT ON;
begin try
--这里模拟插入title列的数据长度,超过了定义时的20
insert into test.dbo.tbb(title,info) values('title1111111111111111111','info');
end try
begin catch
--错误了就回滚
rollback;
insert into tb_error_message
values('tba_delete','trigger',error_message(),getdate())
end catch
END
go
insert into tba
values('11','11')
/*
消息 3930,级别 16,状态 1,过程 tba_delete,第 16 行
当前事务无法提交,而且无法支持写入日志文件的操作。请回滚该事务。
语句已终止。
*/
--查询出错的信息
select *
from tb_error_message
/*
obj_name obj_type err_msg err_date
tba_delete trigger 将截断字符串或二进制数据。 2013-11-08 12:32:16.750
*/
--先保存一个事务点 SAVEPOINT xxx begin try --或者是调用存储过程,或者就直接写代码 exec 发送信息的存储过程 end try begin catch select '执行失败' --一旦出错,只是回滚到上面的事务点,继续执行 ROLLBACK [WORK] TO SAVEPOINT xxx end catch --其他代码
另一张表BB 字段 aa bb cc
如何实现AA表的字段b(为整数型)中的数据 是BB表中的cc字段(为整数型)所有数据记录的总和(sum)!
要求做到BB表数据记录增加的同时AA表中字段b的记录值自动同步更新。
对的,触发器能实现你的需求,另外,索引能加快速度。 因为这种同步的需求,首先,不是跨越服务器的,一般跨越服务器的,可以考虑用数据库同步(异步)、镜像(同步)、日志传送(异步)等技术。 而你现在是在同一台服务器上,要同步2个表的数据,所以用触发器是最合适的,而且触发器本身的特性是,在同一个事务中,只要你的数据插入成功,那么另一个表的数据,也就是同步成功了,同样的,如果插入失败,报错,那么另一个表的数据也不会同步成功。 再有,就是效率的问题,如果每次都sum求和,而你的表里是上亿的数据,这个sum肯定是非常耗时的,所以这里采用的是,你插入1条数据,那么只要把这个插入的数据,通过update 表 set c = c + 插入的值 那么自然就加快了速度,而且不会出现并发的问题。 如果还想进一步加快速度,那么可以考虑,给A表建立索引,因为a表肯定记录也不会少,而且肯定是通过where条件来定义某一条记录,然后update ,这个时候通过索引,就能更快的找到这条记录,然后update。
本站文章为和通数据库网友分享或者投稿,欢迎任何形式的转载,但请务必注明出处.
同时文章内容如有侵犯了您的权益,请联系QQ:970679559,我们会在尽快处理。