powered by simpleCommunicator - 2.0.50     © 2025 Programmizd 02
Форумы / Caché, Ensemble, DeepSee, MiniM, IRIS, GT.M [игнор отключен] [закрыт для гостей] / Триггер AFTER UPDATE срабатывает не всегда
5 сообщений из 5, страница 1 из 1
Триггер AFTER UPDATE срабатывает не всегда
    #38123611
crossa
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Пишу триггер для Cache на обычном SQL.
Таблица:
Код: sql
1.
2.
3.
4.
5.
CREATE TABLE  ENTITY1  (
    ID  INTEGER IDENTITY NOT NULL,
    STEXT  VARCHAR(100),
    ENTITY1_COND  CHAR(1),
    PRIMARY KEY(ID) )



Триггер:
Код: sql
1.
2.
3.
4.
5.
6.
7.
CREATE TRIGGER ENTITY1_TR
    AFTER UPDATE OF ENTITY1_COND ON ENTITY1
    REFERENCING OLD ROW AS OLD_ENTITY1 NEW ROW AS NEW_ENTITY1
    FOR EACH ROW
BEGIN
...
END



Поле ENTITY1_COND используется для выбора какого-либо действия над данными внутри тела триггера: если ENTITY1_COND = 0, выполняется одно действие, если ENTITY1_COND = 1 выполняется другое действие.

Проблема в том, что триггер срабатывает только тогда, когда новое значение ENTITY1_COND отличается от старого значения. Если же при выполнении команды UPDATE старое и новое значение ENTITY1_COND совпадают, то триггер вообще не вызывается:

Код: sql
1.
2.
update entity1 set stext = 'ZZZ', entity1_cond = '1' where id=1
update entity1 set stext = 'DDD', entity1_cond = '1' where id=1



При выполнении второй команды триггер не работает.

Это большая проблема для меня: данный триггер использовался для разных СУБД (SQL Server, Oracle, Firebird, MySQL), и нигде я не припомню такого. В других СУБД триггер всегда срабатывает, если в команде UPDATE присваивается значение полю ENTITY1_COND; и неважно, совпадают старое и новое значения или нет.

Может быть, я что-то неправильно понял? Как в Cache добиться того, чтобы триггер на UPDATE всегда срабатывал?
...
Рейтинг: 0 / 0
Триггер AFTER UPDATE срабатывает не всегда
    #38123752
servit
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
crossa ,

Как Вы узнали, что триггер именно не сработал, а не произошла, например, ошибка?
Код триггера у Вас написан на T-SQL, но, к сожалению, не указан сам код. Был уже вопрос, похожий на Ваш: 12992239

Сделал небольшой тест:Class del.c Extends %Persistent [ SqlTableName = ENTITY1 ]
{

Property SText As %String(MAXLEN = 100) [ SqlFieldName = STEXT ];

Property Entity1Cond As %Char [ SqlFieldName = ENTITY1_COND ];

ClassMethod Fill()
{
  do ..%KillExtent()
  &sql(insert into ENTITY1(STEXT,ENTITY1_COND)values('ZZZ','1'))
  &sql(update ENTITY1 set STEXT='DDD',ENTITY1_COND='1' where id=1)
}

Trigger NewTrigger1 [ Event = UPDATE, Foreach = row, SqlName = ENTITY1_TR, Time = AFTER, UpdateColumnList = Entity1Cond ]
{
  set ^tmp("ENTITY1_COND новое")={ENTITY1_COND*N}
  set ^tmp("ENTITY1_COND старое")={ENTITY1_COND*O}
  set ^tmp("ENTITY1_COND старое и новое отличаются?")=$s({ENTITY1_COND*C}:"Да",1:"Нет")
  set ^tmp("STEXT новое")={STEXT*N}
  set ^tmp("STEXT старое")={STEXT*O}
  set ^tmp("STEXT старое и новое отличаются?")=$s({STEXT*C}:"Да",1:"Нет")
}

}Результат:
Код: plaintext
1.
2.
3.
4.
5.
6.
TEST>do ##class(del.c).Fill()
^tmp("ENTITY1_COND новое")=1
^tmp("ENTITY1_COND старое")=1
^tmp("ENTITY1_COND старое и новое отличаются?")="Нет"
^tmp("STEXT новое")="DDD"
^tmp("STEXT старое")="ZZZ"
^tmp("STEXT старое и новое отличаются?")="Да"
...
Рейтинг: 0 / 0
Триггер AFTER UPDATE срабатывает не всегда
    #38124893
crossa
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
servit
Спасибо за ответ. Мой программный продукт работает с разными типами СУБД, генерит SQL-запросы на создание таблиц, триггеров, индексов, внешних ключей и т.д. Не хотелось бы ради одной лишь Cache писать триггеры на ObjectScript вместо T-SQL; это затруднит модификацию шаблонов SQL-запросов в будущем для моих коллег, кто не имела дела с СУБД Cache.

Версия Cache: Cache for Windows (x86-32) 2012.2.1 (Build 705.0U_SU), демо-версия. Моя программа подключается к базе данных через драйвер ODBC; если бы были какие-то ошибки при выполнении триггера, программа получила об этом сообщение.

Проверил, в каком виде мои триггеры хранятся в базе Cache в виде ObjectScript. Параметр UpdateColumnList в заголовке триггера отсутствует, хотя в SQL-запросе на создание триггера явно указано, что он срабатывает при изменении поля ENTITY1_COND. Вместо это добавилась первая команда в теле триггера, которую я в исходном SQL-запросе не прописывал:

Trigger ENTITY1TR2 [ Event = UPDATE, Foreach = ROW, Language = cache, NewTable = NEW_ENTITY1, OldTable = OLD_ENTITY1, Order = 1, SqlName = ENTITY1_TR2, Time = AFTER ]
{
If '({ENTITY1_COND*C}) Quit // From UPDATE OF field list
Насколько я понимаю, именно поэтому триггер не срабатывает для тех случаев, когда старое и новое значение ENTITY1_COND совпадают. Может быть, дело в символе подчеркивания в названии поля ENTITY1_COND? Как я заметил, Cache очень "нервно" реагирует на имена идентификаторов, где есть этот символ. К сожалению, переименовать поле таблицы не могу, так как это служебное поле для всех видов СУБД.
...
Рейтинг: 0 / 0
Триггер AFTER UPDATE срабатывает не всегда
    #38125094
servit
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
crossaНасколько я понимаю, именно поэтому триггер не срабатывает для тех случаев, когда старое и новое значение ENTITY1_COND совпадают.Всё верно, за это ответственна конструкция UPDATE OF ENTITY1_COND A trigger specified as UPDATE OF is executed only when one or more of the specified columns is updated in a row in the specified table.Если старое и новое значения совпадают, значит и обновления фактически нет. Тогда какой смысл в вызове триггера и в этой конструкции?
crossaНе хотелось бы ради одной лишь Cache писать триггеры на ObjectScript вместо T-SQLИ не нужно. Оставьте триггер на SQL, но тогда уберите UPDATE OF ENTITY1_COND .

Если Ваш триггер немного видоизменить:CREATE TRIGGER ENTITY1_TR
    AFTER UPDATE ON ENTITY1
    REFERENCING OLD ROW AS OLD_ENTITY1 NEW ROW AS NEW_ENTITY1
    FOR EACH ROW
    WHEN (OLD_ENTITY1.ENTITY1_COND!=NEW_ENTITY1.ENTITY1_COND)
    select  1,'bla-bla-bla' -- некий код, то работать будет так же.
...
Рейтинг: 0 / 0
Триггер AFTER UPDATE срабатывает не всегда
    #38125508
crossa
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
servitЕсли старое и новое значения совпадают, значит и обновления фактически нет. Тогда какой смысл в вызове триггера и в этой конструкции?
Это поле - признак того, какая именно операция над данными была выполнена. Если в поле записывается "1", то триггер обрабатывает данные одним способом, если "2" - другим способом и т.д.

В других СУБД (а их уже около десятка, включая, например, старые версии Informix) всё работало как надо. В других СУБД обновлением поля таблицы считается перезаписывание данных в этом поле, даже если новые данные совпадают со старыми. И только в СУБД Cache обновлением поля является изменение данных.

Убрать UPDATE OF ENTITY1_COND - это не лучший выход, так как триггер может содержать действия и над самой таблицей, для которой создан триггер. Придется что-то изобретать. Спасибо за ответ.
...
Рейтинг: 0 / 0
5 сообщений из 5, страница 1 из 1
Форумы / Caché, Ensemble, DeepSee, MiniM, IRIS, GT.M [игнор отключен] [закрыт для гостей] / Триггер AFTER UPDATE срабатывает не всегда
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]