Чтобы предотвратить обновление исходной таблицы при запуске, позволяя обновлению таблицы Slips, вам понадобится триггер INSTEAD OF INSERT
, VIEW
и цепочка прав собственности, чтобы предотвратить прямое изменение базовой таблицы пользователями или их применением. код. Вы не можете попасть туда с использованием традиционного триггера AFTER UPDATE
по причинам, упомянутым ранее в комментариях, а именно потому, что как триггерная вставка, так и инициированное обновление обернуты в одну транзакцию, они должны либо вступить в силу, либо не вступить в силу. Вы не можете совершать только часть транзакции, и вложенная транзакция является частью самой внешней транзакции, в которой она содержится.
Теперь для решения ...
Части 1 - The View Создать представление с той же структурой столбца и обозначением в качестве таблицы, которая имеет вставки триггера, который дает вам все эти проблемы. Что-то вида:
CREATE VIEW [same-name-as-the-table-you-are-using]
AS
SELECT <list-all-columns-explicitly-please-dont-use-star>
FROM <original-table-with-slightly-different-name-now>
Если исходная таблица с именем XXX
затем переименовать его что-то вроде XXX_SINK
и использовать XXX
для просмотра. Разработчики пользователей и приложений должны рассмотреть это представление как «таблицу», которую они используют.
Часть 2 - цепочки владения собственности в цепи устанавливаются в SQL Server, когда объект реферирования и объект ссылки имеют один и тот же владелец. Когда другая сторона (а не владелец) обращается к ссылочному объекту (в этом случае к представлению), разрешения для этой стороны оцениваются по отношению к объекту ссылки, как обычно, но не не оценивается в отношении объекта, на который делается ссылка (в этом случае Таблица). Это была особенность SQL Server с самого начала, но не известна или не понятна ряду разработчиков SQL. Вы можете получить более подробную информацию о ownership chains here.
Вы захотите отклонить права доступа к базе пользователей к таблице и предоставить их представлению. Это означает, что пользователи могут вставлять или обновлять строки только через представление, а не непосредственно в таблицу. Это важно, потому что вы не хотите, чтобы они в обход, что вы будете делать в следующей части ...
Часть 3 - ВМЕСТО Trigger Создание INSTEAD OF
триггера на представлении.Синтаксис подобен синтаксису триггера AFTER
, за исключением слов INSTEAD OF
вместо AFTER
и что никакой операции вставки не произошло еще в момент его запуска, и если сам триггер не активирует обновление в таблице «сток», обновление не будет будет выполняться вообще. Этот триггер может смешивать и сопоставлять все, что пожелает. Подобно триггеру AFTER
, подразумевается транзакция, но выполняются только явные операции модификации данных в самом триггере.
Помните, что триггер должен явно выполнить insert
в нижнюю таблицу раковины. Строки, которые нужно вставить, можно извлечь из специальной таблицы inserted
, как в случае триггера AFTER
. Помните, что (по крайней мере, для SQL Server) может быть добавлено более одной строки (на самом деле в случае оператора insert с нулевой строкой могут быть нулевые строки). Вам нужно будет решить, разрешать ли хорошие строки или запрещать вставку всех строк. Учитывая ваши требования, я подозреваю, что позже.
Собственно дизайн звука базы данных, я бы настоятельно рекомендовал против -
- Спускового ограничение вставки в отдельные строки и
- Использованием любой формы курсора внутри триггера, чтобы иметь дело с многорядным вставки. Вместо этого используйте set-oriented DML.
Хотя текущее приложение может вставлять только строки по одному, база данных не должна налагать такое ограничение.
Разумный RAISERROR
(то есть с разумными значениями серьезности и состояния) не приведет к тому, что что-либо будет отменено или откат.
Выполнение этих действий в этой комбинации должно привести к желаемому результату.
Триггеры запускают неявную транзакцию, поэтому ваша явная транзакция в триггере фактически является вложенной. SQL Server не соблюдает вложенные транзакции, и, вероятно, там что-то происходит. Я бы просто удалил вашу явную транзакцию и посмотрел, работает ли это для вас. –
Исправление к вышеуказанному комментарию. Дело не в том, что SQL Server «не соблюдает вложенные транзакции», но семантика может немного отличаться от того, что вы ожидаете. SQL Server отслеживает уровень вложенности в '@@ trancount', и только внешний' commit' (тот, который заставляет '@@ trancount' переходить от 1 до 0), фактически совершит транзакцию. Откат (без точки сохранения), однако, откат транзакции, принимающей '@@ trancount', равен 0. –
« BEGIN TRAN »является излишним. Он может быть безопасно удален без влияния на поведение триггера, который, как указывает @JohnSpecko, уже имеет неявную транзакцию. Я не ожидаю, что это исправит любую проблему, с которой вы столкнулись. Имеет ли [DC]. [Dbo]. [Slips] есть триггер обновления, и у этого триггера обновления есть оператор ROLLBACK в нем случайно? Что может случиться, так это то, что 'ROLLBACK' откатывает все, включая все вложенные транзакции, включая вашу работу. –