Получить ROWCOUNT от ВМЕСТО ТРИГГЕРА - PullRequest
6 голосов
/ 27 ноября 2010

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

Теперь нам нужно отказаться от некоторых INSERT с использованием триггера 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 или в этих других банках знаний.Это просто случай ТРИГГЕРЫ ЗЛО?

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

Ответы [ 2 ]

3 голосов
/ 27 ноября 2010

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

Оператор

SELECT * FROM INSERTED WHERE COL1 < 5

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

Оператор Put

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
1 голос
/ 22 ноября 2014

Проблема

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

Решение

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

  • SET CONTEXT_INFO / CONTEXT_INFO ()

  • Локальные временные таблицы (то есть таблицы с именами, начинающимися с одного #: #tmp)

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

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

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

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;

Третье: Пройти тест

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
Триггер (после INSERT): 5
Окончательный @@ ROWCOUNT (что мы НЕ хотим): 91

Результаты:

RowsAffected
5

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