Триггер SQL CLR: имя контекстной БД - PullRequest
1 голос
/ 28 июля 2010

Я бы хотел включить / выключить рекурсию триггера в моем триггере SQL CLR. Согласно http://www.devx.com/tips/Tip/30031, мне нужно позвонить

EXEC sp_dboption '<name of db>', 'recursive triggers', 'true'/'false'

Есть ли способ узнать текущее имя БД? При создании триггера я прошу пользователей выбрать один, но я не хочу записывать его в таблицу.

С уважением,

Ответы [ 3 ]

1 голос
/ 24 августа 2015

Существует очень простой способ найти имя базы данных, в которой запускается SQLCLR Trigger: просто установите соединение с Context Connection и получите свойство Database. Вам даже не нужно выполнять запрос: -).

Следующее должно работать во всех типах объектов SQLCLR (хранимая процедура, функция, определяемый пользователем агрегат, определяемый пользователем тип и триггер):

string _DatabaseName;

using (SqlConnection _Connection = new SqlConnection("Context Connection = true;"))
{
    _Connection.Open();
    _DatabaseName = _Connection.Database;
}

Вот и все! Я только что попробовал это в SQLCLR Trigger, и он отлично работает.


Еще одна вещь, о которой следует помнить при ограничении триггеров, запускающих другие триггеры, - это функция TRIGGER_NESTLEVEL . Это лучше работает в триггерах T-SQL, где доступно значение @@PROCID и содержит [object_id] триггера. Таким образом, в триггерах T-SQL вы можете ограничить рекурсию каждого триггера в отдельности, но при этом разрешить триггерам запускать другие триггеры в других таблицах.

В SQLCLR его все еще можно использовать, но без имени триггера вы можете ограничить только все триггеры. Это означает, что вы можете предотвратить запуск любого Триггера любым другим Триггером в любой Таблице, в том числе в той же Таблице, но нет способа ограничить срабатывание только того же Триггера, одновременно разрешив запуск Триггеров для других таблиц, которые могут быть модифицирован соответствующим триггером. Просто используйте Context Connection и запустите SELECT TRIGGER_NESTLEVEL(); через SqlCommand.ExecuteScalar().

1 голос
/ 28 июля 2010

Вы знаете, что такое база данных при создании триггера ...

CREATE TRIGGER etc
....
GO
DECLARE @db varchar(100)
SET @db = DB_NAME()
EXEC sp_dboption @db, 'recursive triggers', 'true'/'false'
0 голосов
/ 28 июля 2010

Я нашел лучшее решение.

Я вообще не должен вызывать EXEC sp_dboption. Вместо этого я должен создать временную таблицу как флаг «нет рекурсии», затем проверить существующую таблицу в начале триггера и выйти, если таблица существует.

Почему временный стол?

  1. Его убивают в конце сеанса. Нет необходимости сбрасывать флаг (в исключительной ситуации), что необходимо для предотвращения постоянного отключения триггера.
  2. AFAIK, он создается и уничтожается независимо для каждого соединения. Таким образом, если пользователь изменяет данные одновременно, конфликта не будет (что неизбежно для EXEC sp_dboption).
...