Вложенные триггеры SQL Server не срабатывают, как ожидалось

Я обновил базу данных SQL Server 6.5 до SQL Server 2012, написав схему с 6.5, исправляя любые проблемы синтаксиса в этом скрипте, а затем я использовал этот скрипт для создания базы данных 2012 года.

В то же время я обновил приложение front-end от PowerBuilder 6 до 12.5.

Когда я выполняю определенное действие в приложении, он вставляет данные в заданную таблицу. Эта таблица имеет триггер, связанный с действием INSERT, и в этом триггере обновляются другие таблицы. Это также вызывает дополнительные триггеры для этих таблиц.

Первоначально приложение PowerBuilder сообщает о следующей ошибке:

Строка изменилась между восстановлением и обновлением.

В базу данных не внесены изменения.

Теперь я понимаю, что означает это сообщение об ошибке, но это то, где он становится действительно "интересным"!

Чтобы понять, что происходит в триггерах, я решил вставить данные в таблицу регистрации из триггеров, чтобы я мог лучше понять поток событий. Это имело довольно неожиданный побочный эффект: приложение PowerBuilder больше не сообщает о каких-либо ошибках, и когда я проверяю базу данных, все данные записываются как ожидалось.

Если я удалю эти строки ведения журнала, приложение снова завершится с сообщением об ошибке, которое было ранее указано.

Мой вопрос: может ли кто-нибудь объяснить, почему добавление некоторых строк ведения журнала может иметь этот побочный эффект? Это почти похоже на то, что вы добавляете некоторые записи, которые записывают данные в таблицу протоколирования, замедляют работу или каким-то образом сериализуют триггеры для запуска в правильном порядке....

Заранее благодарим за любую информацию, которую вы можете предложить :-)

1 ответ

Ну, давайте вспомним, почему это сообщение появляется (у меня есть более подробное объяснение на http://www.techno-kitten.com/PowerBuilder_Help/***************/Database_Irregularities/database_irregularities.html). Это в основном потому, что база данных больше не может находить данные, которые она пытается обновить, на основе предложения WHERE, сгенерированного DataWindow. Триггеры вызывают это, изменяя данные в столбцах в обновленной таблице, поэтому логика WHERE = не выполняется.

Если бы я устранил эту проблему, я бы сделал следующее для обеих версий триггера:

  • извлекать данные в приложении, а также в инструменте СУБД, кэшировать данные из обоих (данные из исходного буфера в ПБ, точка прерывания отладчика в ПБ может помочь) и сравнить столбцы, которые вы ожидаете в предложении WHERE (на стороне клиента манипуляция данными и флаги состояния также могут вызвать эту проблему)
  • внести изменения в данные и инициировать сохранение
  • от точки останова в событиях SQLPreview (это, вероятно, несколько строк, если они вызваны триггером), кэшировать ожидающие утверждения UPDATE
  • в то время как все еще приостановлено в SQLPreview, используйте предложение WHERE в операторах UPDATE для выбора данных с помощью инструмента СУБД

Где-то через все это вы определите, где процесс разрушается в случае сбоя, и выясните, почему он проходит в хорошем случае. Я подозреваю, что вы найдете гораздо более простое решение, чем вы предполагаете.

Удачи,

Терри

licensed under cc by-sa 3.0 with attribution.