触发器里的事务

kkun_3yue3 2009-04-24 10:02:47
/* 监视UPDATE */
ALTER TRIGGER OnStatusChanged
ON 某表
FOR UPDATE
AS
IF(UPDATE([某字段]))
BEGIN
BEGIN TRAN
EXEC 调用一个存储过程

IF(@@error <> 0)
BEGIN
ROLLBACK TRAN
END

COMMIT TRAN
END
GO



如果调用存储过程时出错,会不会回滚到UPDATE操作?

...全文
134 19 打赏 收藏 转发到动态 举报
写回复
用AI写文章
19 条回复
切换为时间正序
请发表友善的回复…
发表回复
kkun_3yue3 2009-04-24
  • 打赏
  • 举报
回复
要不回滚原操作的写法,


默认是回滚原操作的,
taoistong 2009-04-24
  • 打赏
  • 举报
回复


ALTER TRIGGER OnStatusChanged
ON 某表
FOR UPDATE
AS
IF(UPDATE([某字段]))
BEGIN
ALTER TRIGGER OnStatusChanged
ON 某表
FOR UPDATE
AS
IF(UPDATE([某字段]))
BEGIN
BEGIN TRAN
EXEC 调用一个存储过程

IF(@@error <> 0)
BEGIN
ROLLBACK TRAN
END

COMMIT TRAN
END
GO

EXEC 调用一个存储过程

IF(@@error <> 0)
BEGIN
ROLLBACK TRAN
END

COMMIT TRAN
END
GO





这样就是的,不相信你可以测试一下
wzy_love_sly 2009-04-24
  • 打赏
  • 举报
回复
[Quote=引用 10 楼 kkun_3yue3 的回复:]
怎么修改使得只回滚存储过程而不影响原有的UPDATE操作?
就是说,如果能执行存储过程则执行之,不能拉倒,无论如何不要影响原有的UPDATE操作?
谢谢各位了
[/Quote]

触发器里写begin tran已经没有意义了,事务的最高级别已经在触发器的触发语句上
kkun_3yue3 2009-04-24
  • 打赏
  • 举报
回复
怎么修改使得只回滚存储过程而不影响原有的UPDATE操作?
就是说,如果能执行存储过程则执行之,不能拉倒,无论如何不要影响原有的UPDATE操作?
谢谢各位了
hxyabc092088 2009-04-24
  • 打赏
  • 举报
回复
只会回滚存储过程的操作,不影响UPDATE继续执行.
kkun_3yue3 2009-04-24
  • 打赏
  • 举报
回复
/* 监视UPDATE */
ALTER TRIGGER OnStatusChanged
ON A
FOR UPDATE
AS
IF(UPDATE(PRODUCT))
BEGIN
IF @@TRANCOUNT > 1
SAVE TRAN ORIGINAL

BEGIN TRY
UPDATE A SET COST = 999 WHERE ID IN (SELECT TOP 1 ID FROM DELETED)
RAISERROR 130033 'PRINT ERROR'
END TRY

BEGIN CATCH
IF @@TRANCOUNT > 1 /*出错回滚*/
ROLLBACK TRAN ORIGINAL
ELSE
ROLLBACK
BEGIN TRAN
END CATCH
END
GO



SELECT * FROM A

BEGIN TRAN
UPDATE A SET Product = 'KKUN' WHERE ID = 1
COMMIT TRAN




这样会回滚UPDATE操作!~
水族杰纶 2009-04-24
  • 打赏
  • 举报
回复
---經過測試 ,會回滾
IF OBJECT_ID('TA')IS NOT NULL DROP TABLE TA
GO
CREATE TABLE TA( ID INT IDENTITY,性別 NVARCHAR(5) CHECK(性別 IN(N'男',N'女')))
IF OBJECT_ID('PRO_TEST')IS NOT NULL DROP PROC PRO_TEST
GO
CREATE PROC PRO_TEST
@SEX NVARCHAR(5)
AS
INSERT TA SELECT @SEX
GO
IF OBJECT_ID('TB')IS NOT NULL DROP TABLE TB
GO
CREATE TABLE TB(ID INT ,[NAME] VARCHAR(10))
INSERT TB SELECT 1,'張三'
IF OBJECT_ID('TRI_TEST')IS NOT NULL DROP TRIGGER TRI_TEST
GO
CREATE TRIGGER TRI_TEST ON TB
FOR UPDATE
AS
IF UPDATE(ID)
BEGIN TRAN
EXEC PRO_TEST 'TEST'
IF(@@error <> 0)
BEGIN
ROLLBACK TRAN
END

COMMIT TRAN
GO
UPDATE TB SET ID=888 WHERE ID=1
/*伺服器: 訊息 547,層級 16,狀態 1,程序 PRO_TEST,行 4
INSERT 陳述式與 COLUMN CHECK 條件約束 'CK__TA__性別__60A75C0F' 發生衝突。衝突發生於資料庫 'db_study',資料表 'TA', column '性別'。
陳述式已經結束。*/
ChinaJiaBing 2009-04-24
  • 打赏
  • 举报
回复

理论上会...
rucypli 2009-04-24
  • 打赏
  • 举报
回复
触发器本身是隐形事务,所以应该会回滚
arrow_gx 2009-04-24
  • 打赏
  • 举报
回复
顶 2 楼的
claro 2009-04-24
  • 打赏
  • 举报
回复
视情况而定,理论上是。
sdhdy 2009-04-24
  • 打赏
  • 举报
回复
触发器本来就是一个事务,建议你在存储过程里加上事务控制。
  • 打赏
  • 举报
回复
应该会
Ray_Zhang 2009-04-24
  • 打赏
  • 举报
回复
学习
[Quote=引用 16 楼 szx1999 的回复:]
可能还需要建立保存点。
借水兄的数据

SQL codeIF OBJECT_ID('TRI_TEST')IS NOT NULL DROP TRIGGER TRI_TEST
GO
CREATE TRIGGER TRI_TEST ON TB
FOR UPDATE
AS
set xact_abort off
IF UPDATE(ID)
save tran procTran
EXEC PRO_TEST 'TEST'
IF(@@error <> 0)
ROLLBACK TRAN procTran
ELSE
COMMIT TRAN procTran

set xact_abort on
GO

UPDATE TB SET ID=888 WHERE…
[/Quote]
duset 2009-04-24
  • 打赏
  • 举报
回复
[Quote=引用 15 楼 szx1999 的回复:]
触发器的第一行加上:

SQL codeset xact_abort off



如果需要,在最后一行加这句恢复一下:

SQL codeset xact_abort on



几点说明:
1.SQL会把一个表的所有触发器都当作同一个事务的一部分。一旦rollback,全部回滚,包括导致触发的动作。
2.set xact_abort off,使得事务只回滚出错的语句。
[/Quote]

学习了
ai_li7758521 2009-04-24
  • 打赏
  • 举报
回复
学习
等不到来世 2009-04-24
  • 打赏
  • 举报
回复
可能还需要建立保存点。
借水兄的数据
IF OBJECT_ID('TRI_TEST')IS NOT NULL DROP TRIGGER TRI_TEST
GO
CREATE TRIGGER TRI_TEST ON TB
FOR UPDATE
AS
set xact_abort off
IF UPDATE(ID)
save tran procTran
EXEC PRO_TEST 'TEST'
IF(@@error <> 0)
ROLLBACK TRAN procTran
ELSE
COMMIT TRAN procTran

set xact_abort on
GO

UPDATE TB SET ID=888 WHERE ID=1
select * from tb
/*
ID NAME
----------- ----------
888 張三

(1 行受影响)
*/
等不到来世 2009-04-24
  • 打赏
  • 举报
回复
触发器的第一行加上:
set xact_abort off


如果需要,在最后一行加这句恢复一下:
set xact_abort on


几点说明:
1.SQL会把一个表的所有触发器都当作同一个事务的一部分。一旦rollback,全部回滚,包括导致触发的动作。
2.set xact_abort off,使得事务只回滚出错的语句。
wzy_love_sly 2009-04-24
  • 打赏
  • 举报
回复
触发器本身就是事务,在触发器里面开begin tran,就是嵌套事务,它的commit就会无效,想象只能先commit一下,
叫触发器不升级为嵌套事务。如果是存储过程,可以save一个tran 单条回滚。

ALTER TRIGGER OnStatusChanged
ON 某表
FOR UPDATE
AS
begin
if @@trancount>0
commit
IF(UPDATE([某字段]))
EXEC 调用一个存储过程
end

34,873

社区成员

发帖
与我相关
我的任务
社区描述
MS-SQL Server相关内容讨论专区
社区管理员
  • 基础类社区
  • 二月十六
  • 卖水果的net
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧