Текущий архив: 2007.05.27;
Скачать: CL | DM;
ВнизВедение логов изменения некоторой величины Найти похожие ветки
← →
Mr. D. (2007-03-07 16:36) [0]Допустим, есть таблица:
id | SomeField | SomeField_history
id - PK
SomeField - integer
SomeField_history - blob, где ведется лог изменения величины в колонке SomeField
Такой триггер имеем:create trigger my_trig for "TestTable"
active after update position 0
as
declare variable insert_string blob;
begin
if ( old.SomeField <> new.SomeField ) then
begin
insert_string = "LOG " || CAST(new.SomeField as char);
UPDATE "TestTable" t set t.SomeField_history = :insert_string WHERE t.id = new.id;
end
end;
Но с этим тригером при изменении величины SomeField выдается ошибка:Error Message:
----------------------------------------
Unsuccessful execution caused by a system error that precludes
successful execution of subsequent statements.
internal error.
[00542BAF]
Почему же так? :(
← →
Val © (2007-03-07 16:44) [1]апдейт таблицы в триггере после апдейта этой же таблицы?
← →
DrPass © (2007-03-07 16:58) [2]
> Почему же так? :(
Чё такое рекурсия, знаешь?
← →
Mr. D. (2007-03-07 17:48) [3]
> Чё такое рекурсия, знаешь?
знаю! Там же условие стоит:if (old.SomeField <> new.SomeField )
в моем апдейте, который в триггере, SomeField явно не затрагивается, поэтому условие не должно сработать.
← →
Val © (2007-03-07 17:53) [4]мистер, сделай присвоение.
← →
Mr. D. (2007-03-07 18:08) [5]
> мистер, сделай присвоение
я не понял смысла фразы
← →
Mr. D. (2007-03-07 19:32) [6]Народ, подсобите... :(
← →
Johnmen © (2007-03-07 20:10) [7]Чего подсоблядь? Уже сказали - рекурсия.
← →
Mr. D. (2007-03-07 22:18) [8]Johnmen © (07.03.07 20:10) [7]
Чего подсоблядь? Уже сказали - рекурсия
действительно, сказали. Но хочу заметить, что в посте под номером [3] я пояснил свою точку зрения насчет того, почему я считаю, что это не рекурсия.
Там же стоит условие:if (old.SomeField <> new.SomeField )
если поле SomeField есть в UPDATE - то выполняется тело IF"а, в котором да, вызывается UPDATE, но уже SomeField не меняется! Поэтому при вторичном вызове триггера IF не сработает.
← →
Johnmen © (2007-03-07 22:31) [9]
> Mr. D. (07.03.07 22:18) [8]
Да-да, понятно...
Дело в blob, т.к. так апдейтить их нельзя. Как можно? А я не помню...:)
Читай ibase.ru Найдешь ответ - нам расскажешь...
← →
DrPass © (2007-03-07 22:42) [10]
> Там же стоит условие:
>
> if (old.SomeField <> new.SomeField )
Ну и что? А ты мануал читал?
← →
Mr. D. (2007-03-07 23:44) [11]DrPass © (07.03.07 22:42) [10]
Ну и что? А ты мануал читал?
какой мануал? В каком месте?
Если здесь косяк - подскажи, пожалуйста, в чем?
← →
DrPass © (2007-03-08 00:22) [12]
> Mr. D. (07.03.07 23:44) [11]
Первоисточник, естессно - Interbase Data Definition Guide, раздел Working with Triggers.
If a trigger performs an action that causes it to fire again—or fires another trigger that
performs an action that causes it to fire—an infinite loop results. For this reason, it is
important to ensure that a trigger’s actions never cause the trigger to fire, even
indirectly.
Нельзя, вопщем.
← →
Mr. D. (2007-03-08 02:44) [13]DrPass © (08.03.07 0:22) [12]
блин, ну а как же в триггере на апдейт изменить поле таблицы, для которой создан этот триггер?
new.SomeField_history присвоить нельзя, так как в UPDATE вполне возможно это поле не задействовано, поэтому это не возымеет действия...
Что же делать?
← →
Johnmen © (2007-03-09 09:07) [14]
> Mr. D. (08.03.07 02:44) [13]
> new.SomeField_history присвоить нельзя, так как
> в UPDATE вполне возможно это поле не задействовано, поэтому
> это не возымеет действия...
Почему же не возымеет-то?
← →
Сергей М. © (2007-03-09 09:32) [15]
> Что же делать?
Для случая с блобом без UDF не обойтись.
← →
Sergey13 © (2007-03-09 09:37) [16]> [0] Mr. D. (07.03.07 16:36)
А зачем в блобе вести лог? Почему не просто в 3 (4) полях дата - юзер - [старое значение-] новое значение?
← →
DrPass © (2007-03-09 17:25) [17]
> ну а как же в триггере на апдейт изменить поле таблицы,
> для которой создан этот триггер?
Вообще-то это делается простым присваиванием new.blahblahblah=...
← →
Mr. D. (2007-03-10 23:52) [18]Johnmen © (09.03.07 9:07) [14]
Почему же не возымеет-то?
DrPass © (09.03.07 17:25) [17]
Вообще-то это делается простым присваиванием new.blahblahblah=...
не знаю... Проведенный мной эксперименты показывают, как я уже говорил:
Mr. D. (08.03.07 2:44) [13]
так как в UPDATE вполне возможно это поле не задействовано, поэтому это не возымеет действия...
то есть, я когда экспериментировал, если в UPDATE затронуто некое поле, то ему можно сделать:new.blabla = bla
но если например запрос:UPDATE TestTable SET SomeField = 4
То в триггере присвоение:SomeField_history = "bla";
не произведет никакого эффекта. А вот если:UPDATE TestTable SET SomeField = 4, SomeField_history="bla"
то тогда будет.
← →
Johnmen © (2007-03-11 01:22) [19]
> SomeField_history = "bla";не произведет никакого эффекта.
Ты же префикс NEW не указал.
← →
Mr. D. (2007-03-11 02:54) [20]Johnmen © (11.03.07 1:22) [19]
Ты же префикс NEW не указал
Да, ошибся, с руки писал.
В общем, по моим экспрементам выходит, что если UPDATE не затрагивает некое поле, то и new.[поле] это не будет действовать... Не так все на самом деле? Странно тогда...
← →
DrPass © (2007-03-11 02:59) [21]
> В общем, по моим экспрементам выходит, что если UPDATE не
> затрагивает некое поле, то и new.[поле] это не будет действовать.
> ..
Злая клевета на триггеры, конечно. Естественно, триггер должен быть before update, а не after
← →
Mr. D. (2007-03-12 03:40) [22]DrPass © (11.03.07 2:59) [21]
Злая клевета на триггеры, конечно. Естественно, триггер должен быть before update, а не after
да уж :( Действительно, в before надо было делать, а я делал в after... Но возникла проблема:
если рассмотреть такой триггер:create trigger orders_status_history for "ORDERS"
active before update position 11
as
begin
if ( old.STATUS <> new.STATUS ) then
begin
new.STATUS_HISTORY = "Delive to " || CAST(new.STATUS as char);
end
end;
Все работает просто супер! Но вот мне нужно чтобы логи складывались, то есть чтобы была видна вся история изменения поля STATUS:create trigger orders_status_history for "ORDERS"
active before update position 11
as
begin
if ( old.STATUS <> new.STATUS ) then
begin
new.STATUS_HISTORY = new.STATUS_HISTORY || "Delive to " || CAST(new.STATUS as char);
end
end;
вот в этом случае уже выдается:
Error Message:
----------------------------------------
Overflow occurred during data type conversion.
conversion error from string "BLOB".
[00542BAF]
эх.. можно как-нибудь бороться? Счастье то так близко...
← →
atruhin © (2007-03-12 07:00) [23]Ну дак он нормально пишет, что невозможно объеденить BLOB поле со строкой.
← →
atruhin © (2007-03-12 07:02) [24]> Счастье то так близко...
Оно и сейчас недалеко, воспользуйся UDF, найди готовую или напиши.
← →
atruhin © (2007-03-12 07:09) [25]Хотя кончно более правильным будет создать отдельную таблицу куде писать:
ID - измененого объекта, время изменения, кто изменил, что изменил.
Можно посмотреть как реализована история изменений в IBExpert, очень неплохо.
← →
Mr. D. (2007-03-12 13:40) [26]atruhin © (12.03.07 7:00) [23]
Ну дак он нормально пишет, что невозможно объеденить BLOB поле со строкой
а средствами SQL в триггерах этого никак не сделать?
atruhin © (12.03.07 7:02) [24]
Оно и сейчас недалеко, воспользуйся UDF, найди готовую или напиши.
я UDF никогда не пользовался, как подключать, как использовать... В какое хоть направление искать? UDF по работе с blob?
Например: http://www.ibase.ru/d_udf.htm
FreeUDFLib подойдет?
← →
atruhin © (2007-03-12 14:31) [27]Как использовать UDF и как писать есть на ibase, все очень просто.
> FreeUDFLib подойдет?
Смотри там описание есть. Неплохая библиотека, но я ее использую как пример функций,
для реализации того что нужно мне. Вообще серьезно работать с FB без UDF нереально,
ведь в нем потому так мало стандартных функций, что всегда можно дописать, что душе угодно.
А вообще подумай о
> [25] atruhin © (12.03.07 07:09)
← →
G_M_S © (2007-03-12 17:42) [28]
new.STATUS_HISTORY = new.STATUS_HISTORY || "Delive to " || CAST(new.STATUS as char);
1) Поле BLOB должно иметь тип TEXT (кажись 2)
2) new.STATUS_HISTORY = old.STATUS_HISTORY||" "||CAST(new.STATUS as varchar(!длина!))
Страницы: 1 вся ветка
Текущий архив: 2007.05.27;
Скачать: CL | DM;
Память: 0.52 MB
Время: 0.046 c