Есть ли какие-либо преимущества для вызова хранимой процедуры SQLCLR из обычного триггера, а не для немедленного развертывания триггера SQLCLR?
Что ж, есть некоторые различия.То, как эти различия связаны с преимуществами или недостатками, зависит от специфики каждой ситуации.
Триггер T-SQL, вызывающий объект SQLCLR (хранимая процедура или функция)
T-Триггеры SQL могут определять, к какой таблице они подключены, с помощью запроса, подобного следующему:
SELECT ss.[name] AS [SchemaName], so.[name] AS [TableName]
FROM [sys].[objects] so
INNER JOIN [sys].[schemas] ss ON ss.[schema_id] = so.[schema_id]
WHERE so.[object_id] = (SELECT so2.[parent_object_id]
FROM [sys].[objects] so2
WHERE so2.[object_id] = @@PROCID);
Объект SQLCLR, вызываемый из триггера T-SQL, не будет иметь прямого доступа к псевдо-псевдонимам INSERTED
и DELETED
-tables (это также верно для хранимых процедур T-SQL или даже вызовов EXEC()
).Эти таблицы могут быть скопированы в локальные временные таблицы, которые затем могут быть прочитаны из объекта SQLCLR (или хранимой процедуры T-SQL или вызова EXEC()
), но это занимает немного больше времени и требует ввода-вывода для создания таблицы.из псевдотаблицы и снова запишите ее в tempdb
.
Триггер SQLCLR
Триггер SQLCLR может взаимодействовать с INSERTED
и DELETED
псевдотаблицы через динамический SQL (что не может сделать триггер T-SQL).Конечно, если код SQLCLR должен SELECT
из псевдотабликов в первую очередь, тогда вам в значительной степени нужно использовать триггер SQLCLR (иначе сделайте глупый трюк copy-pseudo-tables-to-local-temp-tables).
Триггеры SQLCLR не имеют доступа к @@PROCID
(даже при создании SqlConnection
с использованием Context Connection = true;
), поэтому на самом деле нет простого способа определить, какая таблица изменяласьэто вызвало срабатывание триггера.Я подчеркнул «легко», потому что возможно (хотя я не проверял это) использовать триггер T-SQL, установленный как «первый» триггер в таблице, для установки CONTEXT_INFO
с именем таблицы, но затем вы можетеНе используйте CONTEXT_INFO
для чего-либо еще.Вероятно, есть еще один способ, который я почти разработал, но еще не тестировал его (когда у меня будет возможность проверить, работает ли он, я постараюсь обновить его со ссылкой на инструкции).
Мне нужно получить уведомление об изменении определенного столбца (StatusID) в очень большой таблице.В настоящее время используется ряд служб Windows.Каждый контролирует свой собственный StatusID, то есть запрашивает дБ для конкретного StatusID: ВЫБЕРИТЕ a, b, c ОТ, ГДЕ StatusID = @ status.
Это определенно может быть обработано лучше и без использования SQLCLR.SQLCLR может быть великолепным, но его следует использовать при необходимости.В этом случае вам просто нужна таблица очередей, в которой записываются столбцы PK таблицы для строк, которые меняются.
CREATE TABLE dbo.TableChangeQueue
(
TableChangeQueueID INT IDENTITY(-2140000000, 1)
NOT NULL
CONSTRAINT [PK_TableChangeQueue] PRIMARY KEY,
[a] datatype_a,
[b] datatype_b,
[c] datatype_c
);
Затем используйте обычный триггер T-SQL, чтобы INSERT
войти в эту очередь.,Что-то вроде:
INSERT INTO dbo.TableChangeQueue ([a], [b], [c])
SELECT [a], [b], [c]
FROM INSERTED;
Тогда каждая служба Windows может читать из таблицы очередей (не большой таблицы).После обработки записей удалите их из таблицы очередей на основе их значений TableChangeQueueID
.Вы можете прочитать и удалить их одновременно, используя предложение OUTPUT
в операторе DELETE
, но если процесс завершится неудачей, вы не захотите потерять возможность повторной попытки их обработки.
Это, конечно, простая реализация и позволяет дублировать ключевые записи, если эти строки обновляются более одного раза перед обработкой.Если это проблема (т. Е. Вам необходимо, чтобы значения ключей были уникальными), то есть способы справиться с этим в Trigger.Только будьте осторожны, чтобы триггер не изменил данные, обрабатываемые службой Windows, если только это не представляет проблемы.
Здесь много вариантов, но они не могут быть конкретными, не зная, как процессыРабота.Но независимо от этого, главное состоит в том, чтобы отделить обработку измененных StatusID
s от операторов DML, поскольку триггеры выполняются внутри внутренней сгенерированной системой транзакции.Вот почему вы не хотите обрабатывать измененные строки немедленно как часть этого триггера, поскольку это может легко увеличить блокировку таблицы, поскольку транзакция не завершится, пока не завершится триггер;и если ошибки триггера, то оператор DML получит откат.