Pur*_*ome 26 sql t-sql sql-server triggers sql-server-2008
我在SQL Server 2008数据库的表上有以下触发器.它正在递归,所以我需要阻止它.
插入或更新记录后,我试图只更新该表上的单个字段.
这是触发器:
ALTER TRIGGER [dbo].[tblMediaAfterInsertOrUpdate]
ON [dbo].[tblMedia]
BEFORE INSERT, UPDATE
AS
BEGIN
SET NOCOUNT ON
DECLARE @IdMedia INTEGER,
@NewSubject NVARCHAR(200)
SELECT @IdMedia = IdMedia, @NewSubject = Title
FROM INSERTED
-- Now update the unique subject field.
-- NOTE: dbo.CreateUniqueSubject is my own function.
-- It just does some string manipulation.
UPDATE tblMedia
SET UniqueTitle = dbo.CreateUniqueSubject(@NewSubject) +
CAST((IdMedia) AS VARCHAR(10))
WHERE tblMedia.IdMedia = @IdMedia
END
Run Code Online (Sandbox Code Playgroud)
任何人都可以告诉我如何防止触发器插入再次触发另一个触发器?
Ans*_*sss 52
不确定它是否与OP的问题相关,但是如果你来这里是为了找出如何防止在触发器中发生递归或相互递归,你可以测试这样:
IF TRIGGER_NESTLEVEL() <= 1/*this update is not coming from some other trigger*/
Run Code Online (Sandbox Code Playgroud)
MSDN 链接
Rod*_*igo 33
我看到三种可能性:
禁用触发器递归:
这将阻止触发器触发另一个触发器或再次调用自身.为此,请执行以下命令:
ALTER DATABASE MyDataBase SET RECURSIVE_TRIGGERS OFF
GO
Run Code Online (Sandbox Code Playgroud)使用触发器INSTEAD OF UPDATE,INSERT
使用INSTEAD OF触发器可以控制任何正在更新/插入的列,甚至可以在调用命令之前进行替换.
通过阻止使用IF UPDATE来控制触发器
如果触发器正在调用自身,则测试列将以合理的准确度告诉您.为此,请使用以下IF UPDATE()子句:
ALTER TRIGGER [dbo].[tblMediaAfterInsertOrUpdate]
ON [dbo].[tblMedia]
FOR INSERT, UPDATE
AS
BEGIN
SET NOCOUNT ON
DECLARE @IdMedia INTEGER,
@NewSubject NVARCHAR(200)
IF UPDATE(UniqueTitle)
RETURN;
-- What is the new subject being inserted?
SELECT @IdMedia = IdMedia, @NewSubject = Title
FROM INSERTED
-- Now update the unique subject field.
-- NOTE: dbo.CreateUniqueSubject is my own function.
-- It just does some string manipulation.
UPDATE tblMedia
SET UniqueTitle = dbo.CreateUniqueSubject(@NewSubject) +
CAST((IdMedia) AS VARCHAR(10))
WHERE tblMedia.IdMedia = @IdMedia
END
Run Code Online (Sandbox Code Playgroud)ALTER DATABASE <dbname> SET RECURSIVE_TRIGGERS OFF
Run Code Online (Sandbox Code Playgroud)
ON允许AFTER触发器的递归触发.
OFF仅允许直接递归触发AFTER触发器.要同时禁用AFTER触发器的间接递归,请使用sp_configure将嵌套触发器服务器选项设置为0.
RECURSIVE_TRIGGERS设置为OFF时,仅阻止直接递归.要禁用间接递归,还必须将嵌套触发器服务器选项设置为0.
可以通过检查sys.databases目录视图中的is_recursive_triggers_on列或DATABASEPROPERTYEX函数的IsRecursiveTriggersEnabled属性来确定此选项的状态.
我想我明白了:)
当标题被"更新"(读取:插入或更新)时,然后更新唯一主题.当触发器第二次运行时,uniquesubject字段会更新,因此它会停止并离开触发器.
此外,我已经让它处理了更改的MULTIPLE行 - >我总是忘记触发器.
ALTER TRIGGER [dbo].[tblMediaAfterInsert]
ON [dbo].[tblMedia]
FOR INSERT, UPDATE
AS
BEGIN
SET NOCOUNT ON
-- If the Title is getting inserted OR updated then update the unique subject.
IF UPDATE(Title) BEGIN
-- Now update all the unique subject fields that have been inserted or updated.
UPDATE tblMedia
SET UniqueTitle = dbo.CreateUniqueSubject(b.Title) +
CAST((b.IdMedia) AS VARCHAR(10))
FROM tblMedia a
INNER JOIN INSERTED b on a.IdMedia = b.IdMedia
END
END
Run Code Online (Sandbox Code Playgroud)
TRIGGER_NESTLEVEL可以用于防止特定触发器的递归,但是将触发器的对象ID传递到函数中很重要。否则,当另一个触发器进行插入或更新时,您还可以防止触发该触发器:
IF TRIGGER_NESTLEVEL(OBJECT_ID('dbo.mytrigger')) > 1
BEGIN
PRINT 'mytrigger exiting because TRIGGER_NESTLEVEL > 1 ';
RETURN;
END;
Run Code Online (Sandbox Code Playgroud)
从MSDN:
如果未指定任何参数,则TRIGGER_NESTLEVEL返回调用堆栈上的触发器总数。这包括自身。
参考: 避免递归触发器
您可以有一个单独的 NULLABLE 列来指示是否设置了 UniqueTitle。
在触发器中将其设置为 true 值,如果“INSERTED”中的值为 true,则让触发器不执行任何操作