Подтвердить что ты не робот

Как изменить значения INSERT в триггере SQL Server?

У меня есть таблица 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 и изменить его каждый раз, когда изменяется структура таблицы?

4b9b3361

Ответ 1

Используйте триггер после вставки. Присоедините с псевдо-таблицы 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. Потому что это может привести к тому, что оператор завершит работу до запуска триггера, который сможет что-то исправить. (Пожалуйста, дважды проверьте этот параграф, прежде чем полагаться на него. Прошло некоторое время, так как я написал триггер.)

Ответ 2

Я не уверен, где вы собираетесь получить фактическое новое значение для 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-сервере (означает спуск)

Надеюсь, что это поможет!

Edit:

Если вы хотите сделать его более надежным, чтобы он не зависел от структуры таблицы, вы могли бы использовать триггер 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 

Ответ 3

Таблица Temp может помочь использовать 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 

Этот код не нужно фиксировать, когда новые столбцы добавляются в таблицу.

Но остерегайтесь дополнительных накладных расходов временных таблиц.

Также обратите внимание, что SQL Server запускает один раз для больших операций DML и должен правильно обрабатывать многострочные вставки.

Ответ 4

Вы можете посмотреть триггеры INSTEAD OF.

CREATE TRIGGER Tb_InsteadTrigger on Tb
INSTEAD OF INSERT
AS
BEGIN
...

Это позволит вам манипулировать данными до того, как они войдут в таблицу. Триггер отвечает за вставку данных в таблицу.