Lan*_*rry 24 sql-server triggers sql-server-2008
我有这个数据库触发器:
CREATE TRIGGER setDescToUpper
ON part_numbers
AFTER INSERT,UPDATE
AS
DECLARE @PnumPkid int, @PDesc nvarchar(128)
SET @PnumPkid = (SELECT pnum_pkid FROM inserted)
SET @PDesc = (SELECT UPPER(part_description) FROM inserted)
UPDATE part_numbers set part_description_upper = @PDesc WHERE pnum_pkid=@PnumPkid
GO
Run Code Online (Sandbox Code Playgroud)
这是一个坏主意吗?那就是更新同一个表上的列.我希望它为插入和更新启动.
它有效,我只是害怕周期性的情况.触发器内的更新会一次又一次地触发触发器.那会发生吗?
请不要挑选大写的东西.疯狂的情况.
rse*_*nna 39
它取决于当前在DB上设置的触发器的递归级别.
如果你这样做:
SP_CONFIGURE 'nested_triggers',0
GO
RECONFIGURE
GO
Run Code Online (Sandbox Code Playgroud)
或这个:
ALTER DATABASE db_name
SET RECURSIVE_TRIGGERS OFF
Run Code Online (Sandbox Code Playgroud)
上面的那个触发器不会被再次调用,你会安全的(除非你遇到某种僵局;这可能是可能的,但也许我错了).
不过,我不认为这是一个好主意.更好的选择是使用INSTEAD OF触发器.这样您就可以避免通过DB执行第一次(手动)更新.只执行触发器内定义的那个.
INSTEAD OF INSERT触发器将是这样的:
CREATE TRIGGER setDescToUpper ON part_numbers
INSTEAD OF INSERT
AS
BEGIN
INSERT INTO part_numbers (
colA,
colB,
part_description
) SELECT
colA,
colB,
UPPER(part_description)
) FROM
INSERTED
END
GO
Run Code Online (Sandbox Code Playgroud)
这将自动"替换"原始INSERT语句,并将明确的UPPER调用应用于该part_description
字段.
INSTEAD OF UPDATE触发器将类似(我建议您不要创建单个触发器,将它们分开).
此外,这解决了@Martin评论:它适用于多行插入/更新(您的示例没有).
Jor*_*iss 15
另一种选择是将更新语句包含在IF语句中,并调用TRIGGER_NESTLEVEL()来限制第二次运行更新.
CREATE TRIGGER Table_A_Update ON Table_A AFTER UPDATE
AS
IF ((SELECT TRIGGER_NESTLEVEL()) < 2)
BEGIN
UPDATE a
SET Date_Column = GETDATE()
FROM Table_A a
JOIN inserted i ON a.ID = i.ID
END
Run Code Online (Sandbox Code Playgroud)
当触发器最初运行时,TRIGGER_NESTLEVEL设置为1,因此将执行更新语句.该更新语句将依次触发相同的触发器,除非此时TRIGGER_NESTLEVEL设置为2并且不会执行update语句.
您还可以先检查TRIGGER_NESTLEVEL,如果它大于1,则调用RETURN退出触发器.
IF ((SELECT TRIGGER_NESTLEVEL()) > 1) RETURN;
Run Code Online (Sandbox Code Playgroud)
请改用计算列.使用计算列而不是触发器几乎总是更好的主意.
使用UPPER函数查看计算列的下面示例:
create table #temp (test varchar (10), test2 AS upper(test))
insert #temp (test)
values ('test')
select * from #temp
Run Code Online (Sandbox Code Playgroud)
而不是听起来像破纪录或任何东西,但这是至关重要的.切勿编写在多个记录插入/更新/删除时无法正常工作的触发器.这是一种非常糟糕的做法,因为迟早会发生其中一种情况,并且您的触发器将导致数据完整性问题,因为它不会精确地失败,它只会在其中一条记录上运行该进程.这可能需要很长时间,直到有人发现混乱,并且通过它们通常无法正确修复数据.