我有表Tb
ID | Name | Desc
-------------------------
1 | Sample | sample desc
我想在INSERT上创建一个触发器,它将更改插入Desc
的值,例如:
INSERT INTO Tb(Name, Desc) VALUES ('x', 'y')
将导致
ID | Name | Desc
-------------------------
1 | Sample | sample desc
2 | x | Y edited
在上面的示例中,我得到了插入Desc
的值,将其更改为大写,并在末尾添加了edited
。
这就是我需要的,获取正在插入的Desc
并修改它。
我该怎么做?
在插入更新后处理它会更好吗?或者使用INSTEAD OF INSERT触发并在每次表结构更改时修改它?
答案 0 :(得分:36)
使用后插入触发器。从inserted
伪表加入主键上的Tb
。然后更新desc的值。类似的东西:(但可能无法编译)
CREATE TRIGGER TbFixTb_Trg
ON Tb
AFTER INSERT
AS
BEGIN
UPDATE Tb
SET DESC = SomeTransformationOf(i.DESC)
FROM Tb
INNER JOIN inserted i on i.Id = Tb.Id
END
GO
此插入发生在插入发生后,但在insert
语句完成之前。因此,新的,不正确的值已经放在目标表中。在添加,删除列等时,不需要更改此触发器。
警告在触发器触发之前强制执行完整性约束。因此,您不能设置检查约束来强制执行正确形式的DESC。因为这会导致语句在触发器有机会修复任何内容之前失败。 (请在依赖它之前仔细检查这一段。自从我写了一个触发器以来已经有一段时间了。)
答案 1 :(得分:26)
我不确定你将在哪里获得desc的实际新值,但我认为你是从另一张桌子或其他一些表中得到它的。但是你可能有理由想要这样做,所以下面是我如何去做的一个例子。
你想要的是一个名为INSTEAD OF 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
我已经在那里硬编码了'编辑'这个词,因为我不确定你想要获取值的位置,但你可以轻松地用另一个表中的变量或值替换它。
哦还要确保把[]放在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
答案 2 :(得分:9)
临时表可以帮助使用INSTEAD OF 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
将新列添加到表中时,无需修复此代码。
但要注意some additional overhead of temp tables。
另请注意,SQL Server会针对批量DML操作触发一次,并且必须correctly handle multi-row inserts。
答案 3 :(得分:4)
您可能需要查看INSTEAD OF
触发器。
CREATE TRIGGER Tb_InsteadTrigger on Tb
INSTEAD OF INSERT
AS
BEGIN
...
这将允许您在数据进入表之前对其进行操作。触发器负责将数据插入表中。
答案 4 :(得分:0)
不使用IDENTITY,而是使用UNIQUEIDENTIFIER和NEWID():
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
答案 5 :(得分:0)
您可以使用触发器在 INSERT 之后伪更新记录,但请注意,您实际上是在更新记录,而不是在 INSERT 之前替换值。
CREATE TRIGGER [MISNT].[MyTriggerToReplaceColumnValueOnINSERT]
ON [dbo].[myTableThatIsDoingTheINSERT]
AFTER INSERT --I prefer AFTER as it really is about after the fact!
AS
BEGIN
UPDATE upd
SET upd.ColA = 'some value'
FROM [dbo].[myTableThatIsDoingTheINSERT] AS upd
INNER JOIN inserted AS i ON i.ID = upd.ID
WHERE upd.COLB IS NULL --optional WHERE if you want to only affect certain records
END
GO