Триггер обновления TSQL: соединение вставлено и удалено - PullRequest
2 голосов
/ 10 февраля 2010

У меня есть триггер при обновлении в SQL Server 2008. Мне нужно выполнять действие триггера, только если некоторые столбцы были изменены. Таким образом, я хотел бы проверить, что изменилось.

T-SQL предлагает конструкцию "if update (columnName)". Однако, если было обновлено много строк, и только в одной из них было изменено конкретное значение столбца, «if update ()» должно будет возвращать true. Это заставит меня выполнить действие триггера для гораздо большего количества строк, чем требуется.

Поэтому вместо использования «if update ()» я подумал, что просто присоединю виртуальные удаленные и вставленные таблицы (строки до и после обновления) и сам сравню соответствующие столбцы. Тем не менее, как я могу объединить две таблицы? Я не могу использовать первичный ключ таблицы, поскольку он может быть изменен обновлением. Единственное, о чем я могу думать, - это объединение с помощью row_number (), то есть неявное упорядочение таблиц. Это кажется очень неправильным, и я не знаю, предлагает ли SQL Server какие-либо гарантии того, что строки во вставленных упорядочены так же, как в удаленных.

Ответы [ 5 ]

3 голосов
/ 10 февраля 2010

С вашим дизайном (который позволяет менять первичные ключи) кажется очень сложным создать непротиворечивую логику.

Скажем, у вас есть эта таблица:

id   value
1    2
2    1

и выполните эту операцию:

UPDATE  mytable
SET     id = CASE WHEN id = 1 THEN 2 ELSE 1 END,
        value = CASE WHEN value = 1 THEN 2 ELSE 1 END

, которая обновляет обе записи, но покидает таблицу следующим образом:

id   value
2    1
1    2

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

Весь смысл первичных ключей в том, что они никогда не меняются.

0 голосов
/ 01 мая 2013

Ваш компромисс - простота и ремонтопригодность по сравнению с производительностью если производительность не является приоритетной, используйте непосредственно обновление (YourTriggerActionColumn) если производительность имеет приоритет, то способ сделать это - использовать «if update (PrimaryKeyColumn)», поэтому, если первичный ключ не изменился, используйте вставленное-удаленное соединение, если первичный ключ изменился, тогда проверьте «if update (YourTriggerActionColumn)» так как PK не часто меняются, то большую часть времени будет использоваться метод соединения, вставленный-удаленный, что решит вашу проблему с производительностью. немного поздно, но только мои 2 цента :) 1001 *

0 голосов
/ 10 февраля 2010

Лучше всего было бы (как я уже упоминал в комментарии выше) создать новую таблицу, если это возможно, которая включает все данные в оригинале, но также включает неизменный первичный ключ (работает IDENTITY, или вы можете использовать что-то иначе, если вы предпочитаете). Затем вы можете открыть представление этой новой таблицы, которое имитирует имя и схему исходной таблицы. Это даст вам фиксированный идентификатор, который вы можете использовать для отслеживания изменений по своему желанию.

Все это предполагает, что представление работает адекватно в вашем конкретном случае - если приложение делает что-то очень странное, оно может не работать должным образом, но если оно просто использует стандартный CRUD-стиль SQL, оно должно работать нормально. *

0 голосов
/ 10 февраля 2010

, чтобы предотвратить изменение PK, добавьте это в начало вашего триггера:

IF (UPDATE(yourPKcol1) OR UPDATE(yourPKcol2))
BEGIN 
    RAISERROR('Primary Key change not permitted!',16,1) 
    ROLLBACK
    RETURN
END
0 голосов
/ 10 февраля 2010

Если вы используете столбцы IDENTITY в качестве первичных ключей, проблема с обновленными столбцами PK не возникает.

...