2013-09-29 3 views
4

UPDATE: Использование Update_Columns() не является ответом на этот вопрос, так как поля могут меняться в порядке, который приведет к поломке триггера (Update_Columns зависит от порядка столбцов).Как определить, какие поля были обновлены в триггере обновления.

ОБНОВЛЕНИЕ 2: Я уже знаю, что таблицы с удаленными и вставленными данными содержат данные. Вопрос заключается в том, как определить, что изменилось без необходимости жестко кодировать имена полей, поскольку имена полей могут измениться или могут быть добавлены поля.

Допустим, у меня есть таблица с тремя полями.

Строка уже существует, и теперь пользователь обновляет поля 1 и 2.

Как определить, в Trigger Update, какие поля были обновлены, и то, что до и после значений, где?

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

Table 
Id intField1 charField2 dateField3 
7   3 Fred  1995-03-05 

Updated To 

7   3 Freddy  1995-05-06 

History Table 
_____________ 

Id IdOfRowThatWasUpdated BeforeValue AfterValue (as string) 
1      7 Fred   Freddy 
2      7 1995-03-05  1995-05-06 

Я знаю, что я могу использовать Deleted таблицу, чтобы получить старые значения и вставленная таблицы, чтобы получить новые значения. Однако вопрос заключается в том, как сделать это динамически. Другими словами, фактическая таблица имеет 50 столбцов, и я не хочу жестко кодировать 50 полей в инструкцию SQL, а также, если поля меняются и не хотят беспокоиться о том, чтобы синхронизировать SQL с изменения таблицы.

Грег

+0

возможно дубликат [SQL для обнаружения полей измененных в триггер обновления (SQL Server 2005)?] (Http://stackoverflow.com/questions/434842/sql-to-detect- fields-modified-in-update-trigger-sql-server-2005) –

+0

@HamletHakobyan Вопрос другой: мой вопрос в том, как «динамически» определять, какие поля изменены. –

+0

'поскольку поля могут меняться в порядке' Вы хотите сказать, что вы измените свою схему? Вы можете изменить триггер. Кроме того, можно легко перенести порядковое имя для названия. –

ответ

5

вы можете использовать один из моих favorite XML-tricks для этого:

create trigger utr_Table1_update on Table1 
after update, insert, delete 
as 
begin 
    with cte_inserted as (
     select id, (select t.* for xml raw('row'), type) as data 
     from inserted as t 
    ), cte_deleted as (
     select id, (select t.* for xml raw('row'), type) as data 
     from deleted as t 
    ), cte_i as (
     select 
      c.ID, 
      t.c.value('local-name(.)', 'nvarchar(128)') as Name, 
      t.c.value('.', 'nvarchar(max)') as Value 
     from cte_inserted as c 
      outer apply c.Data.nodes('row/@*') as t(c) 
    ), cte_d as (
     select 
      c.ID, 
      t.c.value('local-name(.)', 'nvarchar(128)') as Name, 
      t.c.value('.', 'nvarchar(max)') as Value 
     from cte_deleted as c 
      outer apply c.Data.nodes('row/@*') as t(c) 
    ) 
    insert into Table1_History (ID, Name, OldValue, NewValue) 
    select 
     isnull(i.ID, d.ID) as ID, 
     isnull(i.Name, d.Name) as Name, 
     d.Value, 
     i.Value 
    from cte_i as i 
     full outer join cte_d as d on d.ID = i.ID and d.Name = i.Name 
    where 
     not exists (select i.value intersect select d.value) 

конец;

sql fiddle demo

+0

Ничего себе, это отлично работает. –

+1

Если новое значение «NULL», а старое значение - это пустая строка или «», то последний предикат следует заменить на 'where i.Value <> d.Value или i.Value IS NULL AND d.Value IS NOT NULL или i.Value NOT NULL и d.Value IS NULL' или 'где EXISTS (SELECT i.Value EXCEPT SELECT d.Value)'. [SQLFiddle] (http://www.sqlfiddle.com/#!3/d41d8/21670) –

+1

@BogdanSahlean Спасибо за это, включит его. –

0

В этом посте:

How to refer to "New", "Old" row for Triggers in SQL server?

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

«вставляемый новая строка на INSERT/UPDATE. DELETED является удаленной строкой на УДАЛИТЬ и обновленный ряд на UPDATE (т.е. старых значений до того, как строка была обновлены)»

Смежные вопросы