У меня есть триггер UPDATE для таблицы, которая отслеживает изменение определенного столбца с одного конкретного значения на любое другое значение. Когда это происходит, он обновляет некоторые связанные данные в другой таблице с помощью одного оператора UPDATE.
Первое, что делает триггер, это проверяет, изменилось ли значение этого столбца в обновленных строках по сравнению со значением, о котором идет речь. Он просто присоединяет INSERTED к DELETED и сравнивает значение в этом столбце. Если ничего не подходит, он выдается на ранней стадии, поэтому оператор UPDATE не выполняется.
IF NOT EXISTS (
SELECT TOP 1 i.CUSTNMBR
FROM INSERTED i
INNER JOIN DELETED d
ON i.CUSTNMBR = d.CUSTNMBR
WHERE d.CUSTCLAS = 'Misc'
AND i.CUSTCLAS != 'Misc'
)
RETURN
В этом случае CUSTNMBR является первичным ключом базовой таблицы. Если я сделаю большое обновление этой таблицы (скажем, 5000+ строк), этот оператор займет AGES, даже если я не коснулся столбца CUSTCLAS. Я могу наблюдать за тем, как это заявление в течение нескольких минут отображается в Profiler.
План исполнения причудливый. Он показывает вставленное сканирование с 3714 выполнениями и ~ 18,5 миллионами выходных строк. Это проходит через фильтр в столбце CUSTCLAS. Он соединяет это (через вложенный цикл) с удаленным сканированием (также фильтруемым по CUSTCLAS), которое выполняется только один раз и имеет 5000 выходных строк.
Какую идиотскую вещь я делаю здесь, чтобы вызвать это? Обратите внимание, что триггер обязательно должен правильно обрабатывать многострочные обновления.
РЕДАКТИРОВАТЬ :
Я также попытался написать это так (на случай, если EXISTS делал что-то неприятное), но это все так же ужасно.
DECLARE @CUSTNMBR varchar(31)
SELECT TOP 1 @CUSTNMBR = i.CUSTNMBR
FROM INSERTED i
INNER JOIN DELETED d
ON i.CUSTNMBR = d.CUSTNMBR
WHERE d.CUSTCLAS = 'Misc'
AND i.CUSTCLAS != 'Misc'
IF @CUSTNMBR IS NULL
RETURN