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

Bru*_*oLM 30 sql t-sql sql-server triggers sql-server-2008

我有桌子 Tb

ID | Name   | Desc
-------------------------
 1 | Sample | sample desc
Run Code Online (Sandbox Code Playgroud)

我想在INSERT上创建一个触发器,它将改变插入的值Desc,例如:

INSERT INTO Tb(Name, Desc) VALUES ('x', 'y')
Run Code Online (Sandbox Code Playgroud)

会导致

ID | Name   | Desc
-------------------------
 1 | Sample | sample desc
 2 | x      | Y edited
Run Code Online (Sandbox Code Playgroud)

在上面的例子中,我得到了插入的值,将其Desc更改为大写并添加edited到最后.

这就是我需要的,得到Desc插入和修改它.

我怎样才能做到这一点?

插入更新后处理它会更好吗?或者使用INSTEAD OF INSERT触发并在每次表结构更改时修改它?

Sha*_*nce 38

使用后插入触发器.从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
Run Code Online (Sandbox Code Playgroud)

在插入发生之后但在insert语句完成之前发生此触发器.因此,新的,不正确的值已经放在目标表中.在添加,删除列等时,不需要更改此触发器.

在触发器触发之前强制执行警告完整性约束.因此,您不能设置检查约束来强制执行正确形式的DESC.因为这会导致语句在触发器有机会修复任何内容之前失败.(请在依赖它之前仔细检查这一段.自从我写了一个触发器以来已经有一段时间了.)


Jon*_*nVD 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
Run Code Online (Sandbox Code Playgroud)

我在那里硬编码了'编辑'这个词,因为我不确定你想要获取值的位置,但你可以很容易地用另一个表中的变量或值替换它.

哦还要确保把[]放在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 
Run Code Online (Sandbox Code Playgroud)


Vad*_*zim 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 
Run Code Online (Sandbox Code Playgroud)

将新列添加到表中时,不需要修复此代码.

但要注意临时表一些额外开销.

另请注意,SQL Server会针对批量DML操作触发一次,并且必须正确处理多行插入.

  • @Anders,我想,这种方法可能与 [IDENTITY](http://stackoverflow.com/questions/16766963/insert-record-to-sql-table-with-identity-column) 列不兼容。但您也可以尝试将此列删除到触发器内的“#tmp”表中。 (2认同)