Вход в таблицу в триггере SQL Server - PullRequest
4 голосов
/ 11 мая 2010

Я кодирую триггер SQL Server 2005. Я хочу сделать некоторые записи во время выполнения триггера, используя инструкцию INSERT в моей таблице журнала. Когда возникает ошибка во время выполнения, я хочу вызвать ошибку и отменить действие, которое вызывает выполнение триггера, но не потерять записи журнала. Каков наилучший способ добиться этого?

Теперь мой триггер регистрирует все, кроме ситуации, когда возникает ошибка - из-за ROLLBACK. Оператор RAISERROR необходим для информирования вызывающей программы об ошибке.

Теперь мой код обработки ошибок выглядит следующим образом:

if (@err = 1)
begin
    INSERT INTO dbo.log(date, entry) SELECT getdate(), 'ERROR: ' + out from #output
    RAISERROR (@msg, 16, 1)
    rollback transaction
    return
end

Ответы [ 4 ]

7 голосов
/ 11 мая 2010

Другой возможный вариант - использовать табличную переменную для записи информации, которую вы хотите сохранить в вашей таблице постоянного журнала. Табличные переменные не откатываются, если задана команда ROLLBACK TRANSACTION. Пример кода ниже ...



--- Declare table variable
DECLARE @ErrorTable TABLE
  ( [DATE]  smalldatetime,
    [ENTRY] varchar(64) )

DECLARE @nErrorVar  int

--- Open Transaction
BEGIN TRANSACTION

--- Pretend to cause an error and catch the error code
SET @nErrorVar = 1  --- @@ERROR

IF (@nErrorVar = 1)
  BEGIN

    --- Insert error info table variable
    INSERT INTO @ErrorTable 
      ( [Date], [Entry] )
    SELECT
        getdate(), 'Error Message Goes Here'

    RAISERROR('Error Message Goes Here', 16, 1)

    ROLLBACK TRANSACTION

    --- Change this to actually insert into your permanent log table
    SELECT  *
    FROM    @ErrorTable

  END

IF @@TRANCOUNT  0
  PRINT 'Open Transactions Exist'
ELSE
  PRINT 'No Open Transactions'
2 голосов
/ 13 сентября 2011

Не знаю, думаю ли я слишком просто, но почему бы просто не изменить порядок обработчика ошибок, чтобы вставить ПОСЛЕ отката ??

if (@err = 1)
begin
    RAISERROR (@msg, 16, 1)
    rollback transaction
    INSERT INTO dbo.log(date, entry) SELECT getdate(), 'ERROR: ' + out from #output
    return
end
2 голосов
/ 11 мая 2010

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

На ум приходят два варианта:

  • использовать Service Broker для ведения журнала - помещать данные журнала в очередь, получать и сохранять данные «на другой стороне канала» (т. Е. В другом процессе / соединении / транзакции)
  • использовать OPENQUERY - вам нужно зарегистрировать свой собственный сервер в качестве «связанного сервера» и выполнять запросы «удаленно» (я знаю, это выглядит немного странно, но в любом случае это вариант ... )

НТН

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