Roc*_*och 8 sql-server triggers sql-server-2000 infinite-loop
我想知道无论如何我都可以在两个表上添加触发器,将数据复制到另一个表.
例如:
我有一个两个用户表,users_V1和users_V2,当用一个V1应用程序更新用户时,它会激活一个触发器,在users_V2中更新它.
如果我想在V2表上添加相同的触发器以便在V2中更新用户时更新V1中的数据,它是否会进入无限循环?有没有办法避免这种情况.
我不建议在处理过程中明确禁用触发器 - 这可能会导致奇怪的副作用.
检测(和防止)触发器中循环的最可靠方法是使用CONTEXT_INFO().
例:
CREATE TRIGGER tr_Table1_Update
ON Table1
FOR UPDATE AS
DECLARE @ctx VARBINARY(128)
SELECT @ctx = CONTEXT_INFO()
IF @ctx = 0xFF
RETURN
SET @ctx = 0xFF
-- Trigger logic goes here
Run Code Online (Sandbox Code Playgroud)
有关更详细的示例,请参阅此链接.
CONTEXT_INFO()SQL Server 2000中的注意事项:
支持上下文信息,但显然CONTEXT_INFO功能不支持.你必须改用它:
SELECT @ctx = context_info
FROM master.dbo.sysprocesses
WHERE spid = @@SPID
Run Code Online (Sandbox Code Playgroud)
使用TRIGGER_NESTLEVEL()来限制触发器递归,或者
检查目标表是否需要UPDATE:
IF (SELECT COUNT(1)
FROM users_V1
INNER JOIN inserted ON users_V1.ID = inserted.ID
WHERE users_V1.field1 <> inserted.field1
OR users_V1.field2 <> inserted.field2) > 0 BEGIN
UPDATE users_V1 SET ...
Run Code Online (Sandbox Code Playgroud)小智 5
我有同样的问题。我尝试使用 CONTEXT_INFO() 但这是一个会话变量,所以它只在第一次工作!然后下次在会话期间触发触发器时,这将不起作用。所以我最终使用了一个变量,该变量在每个受影响的触发器中返回 Nest Level 以退出。
CREATE TRIGGER tr_Table1_Update
ON Table1
FOR UPDATE AS
BEGIN
--Prevents Second Nested Call
IF @@NESTLEVEL>1 RETURN
--Trigger logic goes here
END
Run Code Online (Sandbox Code Playgroud)
注意:或者如果要停止所有嵌套调用,请使用@@NESTLEVEL>0
另一个注意事项——本文中关于嵌套调用和递归调用似乎有很多混淆。最初的海报指的是嵌套触发器,其中一个触发器会导致另一个触发器触发,这将导致第一个触发器再次触发,依此类推。这是嵌套的,但根据 SQL Server,不是递归的,因为触发器没有直接调用/触发自身。递归不是“一个触发器[正在]调用另一个”。这是嵌套的,但不一定是递归的。您可以通过使用此处提到的一些设置启用/禁用递归和嵌套来测试这一点:关于嵌套的博客文章
| 归档时间: |
|
| 查看次数: |
10937 次 |
| 最近记录: |