MSSQL: отключить триггеры для одного INSERT - PullRequest
16 голосов
/ 30 января 2009

Этот вопрос очень похож на SQL Server 2005: T-SQL для временного отключения триггера

Однако я не хочу отключать все триггеры и даже не для пакета команд, а только для одного INSERT.

Мне приходится иметь дело с системой магазинов, где первоначальный автор помещает некоторую логику приложения в триггер (плохая идея!). Эта логика приложения работает хорошо, если вы не пытаетесь вставить данные не так, как в исходном «интерфейсе администрирования». Моя задача - написать инструмент «импорт из промежуточной системы», чтобы у меня были все данные. Когда я пытаюсь вставить его, триггер перезаписывает существующий код продукта (а не числовой идентификатор IDENTITY!) Созданным. Для генерации кода он использует автоматически сгенерированный идентификатор вставки в другую таблицу, поэтому я даже не могу с @@ IDENTITY найти мой только что вставленный столбец и ОБНОВИТЬ вставленную строку с фактическим кодом продукта.

Любой способ, которым я могу пойти, чтобы избежать крайне неловкого кода (вставьте несколько случайных символов в название продукта, а затем попытайтесь найти строку со случайными символами, чтобы обновить его).

Итак: есть ли способ отключить триггеры (даже один) для только для одного INSERT?

Ответы [ 7 ]

16 голосов
/ 30 января 2009

Вы можете найти это полезным:

Отключение триггера для определенного оператора SQL или сеанса

Но есть и другая проблема, с которой вы можете столкнуться. Если я правильно понимаю ситуацию, в которой вы находитесь, ваша система по умолчанию автоматически вставляет код продукта (генерируя значение). Теперь вам нужно вставить продукт, созданный какой-либо промежуточной системой, и для этого продукта его код продукта был создан промежуточной системой, и вы хотите вставить его в действующую систему вручную.

Если вам действительно нужно это сделать, вам нужно убедиться, что коды, созданные вашим живым приложением в будущем, не будут конфликтовать с кодом, который вы вставили вручную - я предполагаю, что они должны быть уникальными.

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

12 голосов
/ 30 января 2009

Вы можете отключить триггеры для таблицы, используя:

ALTER TABLE MyTable DISABLE TRIGGER ALL

Но это сделало бы это для всех сессий, а не только для вашего текущего соединения ... что, очевидно, очень плохая вещь: -)

Лучшим способом было бы изменить сам триггер, чтобы он принимал решение о том, нужно ли ему запускаться, будь то с флагом «вставить тип» в таблице или каким-либо другим способом, если вы уже храните тип сортировать.

5 голосов
/ 30 января 2009

Вместо отключения триггеров нельзя изменить поведение триггера. Добавьте в эту таблицу новый обнуляемый столбец с именем "ppedFromImport ".

В триггере измените код так, чтобы бит сбоя триггера выполнялся только в строках, в которых "ppedFromImport "равен нулю. Когда вы вставляете свои записи, устанавливаете "ppedFromImport "в нечто отличное от NULL.

3 голосов
/ 21 апреля 2011

Отключить триггер, вставить, зафиксировать.

SET IDENTITY_INSERT Test ON
GO

BEGIN TRAN

DISABLE TRIGGER trg_Test ON Test

INSERT INTO Test (MyId, MyField) 
    VALUES (999, 'foo')

ENABLE TRIGGER trg_Test ON Test

COMMIT TRAN

SET IDENTITY_INSERT Test OFF
GO
1 голос
/ 30 января 2009

Я вижу много вещей, которые могут создать проблему. Сначала измените триггер, чтобы рассмотреть возможность импорта нескольких записей. Это может решить вашу проблему. НЕ ВЫКЛЮЧАЙТЕ курок, так как он выключен для всех, а не только для вас. Если вам необходимо перевести базу данных в однопользовательский режим, прежде чем делать это, и выполнять свою задачу в нерабочее время.

Далее, ни при каких обстоятельствах никогда не используйте @@ identity, чтобы получить только что введенное значение! Вместо этого используйте scope_identity. @@ identity вернет неправильное значение, если в таблице есть триггеры, которые также выполняют вставки в другие таблицы с полями идентификации. Если вы используете @@ identity прямо сейчас в своей системе (поскольку мы знаем, что в вашей системе есть триггеры), вашим первоочередным приоритетом должно быть немедленное обнаружение и изменение всех экземпляров @@ identity в вашем коде. У вас могут возникнуть серьезные проблемы с целостностью данных, если у вас их нет. Это проблема «остановить всю работу, пока это не будет исправлено».

Что касается получения информации, которую вы только что вставили, рассмотрите возможность создания batchid как части вашей вставки, а затем добавьте столбец с именем batchid (который можно обнулять, чтобы он не влиял на другие вставки) в таблицу. Затем вы можете перезвонить то, что вы вставили с помощью batchid.

1 голос
/ 30 января 2009

Можно ли проверить SUSER_SNAME () и запускать только в контексте интерфейса администрирования?

0 голосов
/ 30 января 2009

Если вы вставляете, используя BULK INSERT, вы можете отключить триггеры только для вставки.

Я уверен, что для массовой вставки потребуется импорт файла данных в файловой системе, поэтому вы не можете просто использовать T-SQL.

Чтобы использовать BULK INSERT, вам необходимы разрешения INSERT и ADMINISTRATOR BULK OPERATION. Если вы отключите триггеры или ограничения, вам также потребуется разрешение ALTER TABLE.

Если вы используете проверку подлинности Windows, вашему пользователю Windows потребуется доступ на чтение из файла. при использовании аутентификации в смешанном режиме учетной записи службы сервера SQl необходим доступ на чтение из файла.

При импорте с использованием BULK IMPORT триггеры по умолчанию отключены.

Дополнительная информация: http://msdn.microsoft.com/en-us/library/ms188365.aspx

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...