如何在SQL Server上编辑触发器中插入的值?
我有表如何在SQL Server上编辑触发器中插入的值?,sql,sql-server,sql-server-2008,tsql,triggers,Sql,Sql Server,Sql Server 2008,Tsql,Triggers,我有表Tb ID | Name | Desc ------------------------- 1 | Sample | sample desc 我想在INSERT上创建一个触发器,该触发器将更改insertingDesc的值,例如: INSERT INTO Tb(Name, Desc) VALUES ('x', 'y') 将导致 ID | Name | Desc ------------------------- 1 | Sample | sample desc 2 | x
Tb
ID | Name | Desc
-------------------------
1 | Sample | sample desc
我想在INSERT上创建一个触发器,该触发器将更改insertingDesc
的值,例如:
INSERT INTO Tb(Name, Desc) VALUES ('x', 'y')
将导致
ID | Name | Desc
-------------------------
1 | Sample | sample desc
2 | x | Y edited
在上面的例子中,我得到了insertingDesc
的值,将其改为大写,并在末尾添加了edited
这就是我需要的,获取插入的Desc
,并对其进行修改
我该怎么做
在插入后进行更新是否更好?或者使用INSERT而不是INSERT生成触发器,并在每次表结构更改时对其进行修改?您可能希望查看
而不是触发器
CREATE TRIGGER Tb_InsteadTrigger on Tb
INSTEAD OF INSERT
AS
BEGIN
...
这将允许您在数据进入表之前对其进行操作。触发器负责将数据插入表中。我不确定从何处获取desc的实际新值,但我假设您是从另一个表或类似的表中获取的。但是你可能有这样做的理由,所以下面是一个我将如何去做的例子
您需要的是一个INSTEAD OF INSERT触发器,它使用您提供的每个逻辑在表上触发而不是INSERT
CREATE TRIGGER trgUpdateDesc
ON Tb
INSTEAD OF INSERT
AS
BEGIN
SET NOCOUNT ON;
INSERT INTO Tb (Name, [Desc])
SELECT Name, [Desc] + 'edited'
FROM inserted
END
GO
我在这里硬编码了“edited”一词,因为我不确定要从哪里获取值,但您可以轻松地用变量或其他表中的值替换它
哦,还要确保在Desc周围加上[],因为它是sql server中的一个关键字(代表降序)
希望有帮助
编辑:
如果您想让它更健壮一点,这样它就不会太依赖于表结构,那么您可以使用AFTER INSERT触发器来像这样更新该字段
CREATE TRIGGER [dbo].[trgUpdateDesc]
ON [dbo].[Tb]
AFTER INSERT
AS
BEGIN
SET NOCOUNT ON;
UPDATE Tb
SET [Desc] = UPPER(inserted.[Desc]) + ' Edited'
FROM inserted INNER JOIN Tb On inserted.id = Tb.id
END
使用插入后触发器。从插入的伪表连接到主键上的Tb
。然后更新desc的值,比如:(但可能无法编译)
此触发器发生在插入之后,但在insert
语句完成之前。因此,新的、不正确的值已放置在目标表中。在添加、删除列时,不需要更改此触发器
警告在后触发器触发之前强制执行完整性约束。因此,不能使用check约束来强制执行适当形式的DESC。因为这会导致在触发器有机会修复任何内容之前语句失败。(在依赖它之前,请仔细检查此段落。我已经有一段时间没有编写触发器了。)临时表可以帮助使用而不是INSERT
触发器,同时避免显式列出所有不相关的表列:
CREATE TRIGGER trgUpdateDesc
ON Tb
INSTEAD OF INSERT
AS
BEGIN
SET NOCOUNT ON;
select * into #tmp from inserted;
UPDATE #tmp SET Desc = Desc + 'edited' --where ...;
insert into Tb select * from #tmp;
drop table #tmp;
END
将新列添加到表中时,不需要修复此代码
但是要小心
还请注意,SQL Server为批量DML操作触发一次fire,并且必须触发。不要使用IDENTITY,而是使用UNIQUEIDENTIFIER和NEWID()
你不能换一种方式吗?我个人讨厌当我看到数据上发生奇怪的事情时,我终于意识到一个幽灵触发器正在做一些事情,我将用它来修复一个来自我无法访问的代码的问题。它插入一个项目的url
,但它不会删除重音符号和特殊字符,我会让触发器为我这样做。这并不是一个很难的概念,它让我觉得微软不能提供像Oracle那样的简单功能,在Oracle中,你可以在插入之前通过编辑:新值来修改任何值。i、 e.如果我想在插入用户名之前总是将用户名强制转换为upper(假设出于某种原因我不能在代码中这样做),那么可以使用一个before-insert触发器:NEW.username:=upper(:NEW.username)。但是,在SQL Server中,不能对插入的临时表中的值进行等效,这真的很糟糕。是的,可以。在instead of触发器中,只需运行insert语句,将插入表中的所有列选择到实际表中,但修改要设置为上限的列的select。例如,在insert而不是insert触发器中,只需运行类似于insert into Table(a,b,c)的语句,从inserted中选择a,ToUpper(b),c。微软技术公司将甲骨文从水中击退。我想获取插入的Desc
的值并对其进行修改。我应该这么说。我会更新我的问题,很抱歉,如果我的表更改了怎么办?我每次都要更新触发器?难道没有其他方法可以做到这一点吗?此外,此解决方案不会使实际插入的值可用于输出
子句!在这种情况下,“Trgt”是什么?@CodenameCain是个错误。应该是Tb
,或者from子句需要是fromtrb-Trgt
。感谢您捕捉到这一点。这会产生以下错误:只有在使用列列表且打开identity_INSERT时,才能为表“Tb”中的identity列指定显式值。@Anders,我想,这种方法可能与列不兼容。但您也可以尝试将此列放到触发器内的#tmp
表中。
CREATE TRIGGER trgUpdateDesc
ON Tb
INSTEAD OF INSERT
AS
BEGIN
SET NOCOUNT ON;
select * into #tmp from inserted;
UPDATE #tmp SET Desc = Desc + 'edited' --where ...;
insert into Tb select * from #tmp;
drop table #tmp;
END
CREATE TRIGGER MyTrigger ON MyTable INSTEAD OF INSERT AS BEGIN
; select * into #MyTriggertTempTable from inserted
; update #MyTriggertTempTable set ID=NEWID() where ID is null
; insert into MyTable select * from #MyTriggertTempTable
END