如何在SQL Server的触发器中编辑INSERT的值?

时间:2010-08-26 22:39:01

标签: sql sql-server sql-server-2008 tsql triggers

我有表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触发并在每次表结构更改时修改它?

6 个答案:

答案 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