Как изменить значения 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 и изменить его каждый раз, когда изменяется структура таблицы?
Ответы
Ответ 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
...
Это позволит вам манипулировать данными до того, как они войдут в таблицу. Триггер отвечает за вставку данных в таблицу.