Получить ROWCOUNT из вместо триггера

устаревшее приложение выполняет вставку в таблицу с триггером вместо триггера и впоследствии использует rowcount для дальнейшей обработки.

Теперь нам нужно отказаться от некоторых вставок с использованием INSTEAD OF INSERT триггер.

проблема в том, что @@ROWCOUNT по-прежнему возвращает число попытка вставками.

например, фиктивный триггер, который никогда не завершит вставку, может быть

ALTER TRIGGER [dbo].[trig_ACCOUNT_CREDITS_RunningTotalINSERT]
   ON  [dbo].[ACCOUNT_CREDITS] 
   INSTEAD OF INSERT
AS 
BEGIN
 --tried with NOCOUNT ON and OFF
 SET NOCOUNT OFF;

 --This is an example of the branching logic that might determine 
 --whether or not to do the INSERT
IF 1=2 --no insert will ever occur (example only)
BEGIN
    INSERT INTO dbo.ACCOUNT_CREDITS (COL1, COL2)
    SELECT COL1, COL2 from INSERTED
END
END

и некоторые инструкции INSERT может быть

--No rows will be inserted because value of COL1 < 5
INSERT INTO dbo.ACCOUNT_CREDITS (COL1, COL2) VALUES ( 3, 3)

--We would assume row count to be 0, but returns 1
select @@ROWCOUNT

--No rows will be inserted because value of COL1 < 5       
INSERT INTO dbo.ACCOUNT_CREDITS (COL1, COL2) 
SELECT 1, 1
union all
SELECT 2, 2

--We would assume row count to be 0, but returns 2
select @@ROWCOUNT

Я могу обойти проблему, но меня беспокоит, что я не могу доверять @@ROWCOUNT. Я не могу найти ссылки на эту проблему на SO или those другое банки знаний. Это просто случай ТРИГГЕРЫ-ЭТО ЗЛО?

могу ли я повлиять на @@ROWCOUNT?

2 ответов


некоторые операторы могут изменить @@ROWCOUNT внутри триггера.

сообщении

SELECT * FROM INSERTED WHERE COL1 < 5

выполняет и устанавливает @@ROWCOUNT в 1

положите заявления

SET NOCOUNT ON;

затем

IF NOT EXISTS (SELECT * FROM INSERTED WHERE COL1 < 5)
BEGIN
    SET NOCOUNT OFF;

    INSERT INTO dbo.ACCOUNT_CREDITS (COL1, COL2)
    SELECT COL1, COL2 from INSERTED
END

Проблема

мне нужна информация в контексте основного процесса, которая доступна только в контексте триггера.

Решение

получают ли @@ROWCOUNT или что-нибудь другое С триггер, или даже передача информации to триггер, существует два метода, которые позволяют обмениваться информацией с триггерами:

я опубликовал пример использования CONTEXT_INFO в ответе на соответствующий вопрос в DBA.Клиент StackExchange: передача информации о том, кто удалил запись на триггер удаления. В комментариях к этому ответу было обсуждение, связанное с возможными осложнениями вокруг CONTEXT_INFO, вот я и выложил еще один ответ по этому вопросу, используя вместо этого временную таблицу.

так как этот пример касался отправки информации to триггер, ниже приведен пример получения информации С триггер, поскольку это то, о чем этот вопрос:

первый: создать простую таблицу

CREATE TABLE dbo.InsteadOfTriggerTest (Col1 INT);

второй: создать триггер

CREATE TRIGGER dbo.tr_InsteadOfTriggerTest
   ON dbo.InsteadOfTriggerTest
   INSTEAD OF INSERT
AS
BEGIN
   PRINT 'Trigger (starting): ' + CONVERT(NVARCHAR(50), @@ROWCOUNT);

   SET NOCOUNT ON; -- do AFTER the PRINT else @@ROWCOUNT will be 0

   DECLARE @Rows INT;
   INSERT INTO dbo.InsteadOfTriggerTest (Col1)
      SELECT TOP (5) ins.Col1
      FROM inserted ins;

   SET @Rows = @@ROWCOUNT;
   PRINT 'Trigger (after INSERT): ' + CONVERT(NVARCHAR(50), @Rows);

   -- make sure temp table exists; no error if table is missing
   IF (OBJECT_ID('tempdb..#TriggerRows') IS NOT NULL)
   BEGIN
      INSERT INTO #TriggerRows (RowsAffected)
      VALUES (@Rows);
   END;
END;

третий: Do тест

SET NOCOUNT ON;

IF (OBJECT_ID('tempdb..#TriggerRows') IS NOT NULL)
BEGIN
    DROP TABLE #TriggerRows;
END;
CREATE TABLE #TriggerRows (RowsAffected INT);

INSERT INTO dbo.InsteadOfTriggerTest (Col1)
   SELECT so.[object_id]
   FROM   [master].[sys].[objects] so;

PRINT 'Final @@ROWCOUNT (what we do NOT want): ' + CONVERT(NVARCHAR(50), @@ROWCOUNT);

SELECT * FROM #TriggerRows;

вывод (на вкладке Сообщения):

триггер (запуск): 91
Триггер (после вставки): 5
Final @@ROWCOUNT (чего мы не хотим): 91

результаты:

RowsAffected
5