создать временную таблицу данных триггера - PullRequest
3 голосов
/ 22 марта 2011

Я пытаюсь создать триггер аудита, не указывая список столбцов более одного раза.

С этой целью я хочу создать временную таблицу содержимого ВСТАВЛЕННЫХ или УДАЛЕННЫХ данных в триггере, а затем обработать ее в таблицу аудита.

Если я использую это:

IF @ChangeType = 'D'
  SELECT * INTO #tmp FROM DELETED
ELSE
  SELECT * INTO #tmp FROM INSERTED

Затем я получаю ошибку компиляции во втором SELECT * INTO, что таблица #tmp уже существует.

Если я попытаюсь обойти это с помощью динамического SQL:

SET @Sql = 'SELECT * INTO #tmp FROM '
IF @ChangeType = 'D'
   SET @Sql = @Sq + 'DELETED'
ELSE
   SET @Sql = @Sql + 'INSERTED'

EXEC (@Sql)

Тогда я получаю сообщение об ошибке, что таблицы DELETED и INSERTED не существуют.

Как я могу получить таблицы INSERTED и DELETED в триггере во временную или другую таблицу в памяти?

Ответы [ 3 ]

4 голосов
/ 22 марта 2011

Попробуйте создать временную таблицу вне if, например:

SELECT TOP 0 * INTO #tmp FROM DELETED

IF @ChangeType = 'D'
  INSERT INTO #tmp SELECT * FROM DELETED
ELSE
  INSERT INTO #tmp SELECT * FROM INSERTED
1 голос
/ 22 марта 2011

Это известная проблема из-за разрешения-разбора объекта временной таблицы.С двумя операторами SELECT - INTO в одной и той же области SQL Server выбрасывает полотенце.

SELECT * INTO #tmp FROM DELETED WHERE 1=0
IF @ChangeType = 'D'
  INSERT #tmp SELECT * FROM DELETED
ELSE
  INSERT #tmp SELECT * FROM INSERTED
0 голосов
/ 22 марта 2011

Мне было бы интересно узнать, зачем вам сначала копировать данные в другую таблицу. Но это не по теме ...

Временная таблица (#temp) условно хранится на диске, а переменные таблицы (@temp) условно хранятся только в памяти и могут быть более оптимальными для небольших задач. (Предполагается, что записи в таблицу будут влиять только на небольшое количество строк.)

Временные таблицы, однако, могут быть созданы с помощью трюка SELECT INTO, избегая необходимости заранее знать определение таблицы.

Если вы заранее знаете определение таблицы, не можете ли вы просто использовать что-то вроде следующего?

DECLARE @temp TABLE (id AS INT, val as INT)

IF @ChangeType = 'D'
   INSERT INTO @temp SELECT * FROM DELETED
ELSE
   INSERT INTO @temp SELECT * FROM INSERTED


Лично я бы даже не стал использовать *, если это возможно. Ваши последующие запросы будут использовать только определенные поля, поэтому я буду копировать только те поля, которые я использовал. Это дает дополнительное преимущество: если поля добавляются в таблицу, код не нарушается ...

DECLARE @temp TABLE (id AS INT, val as INT)

IF @ChangeType = 'D'
   INSERT INTO @temp SELECT id, val FROM DELETED
ELSE
   INSERT INTO @temp SELECT id, val FROM INSERTED


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

...