Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Базы";
Текущий архив: 2007.05.27;
Скачать: [xml.tar.bz2];

Вниз

Ведение логов изменения некоторой величины   Найти похожие ветки 

 
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;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.52 MB
Время: 0.048 c
11-1159933318
georgy
2006-10-04 07:41
2007.05.27
Edit.OnChange как это на WIN API?


15-1178009480
Nic
2007-05-01 12:51
2007.05.27
Глючит Canvas в Win Vista


15-1177774830
oldman
2007-04-28 19:40
2007.05.27
Ну вот и суббота (которая понедельник) на исходе...


2-1178514567
Officeman
2007-05-07 09:09
2007.05.27
Как вызввать функцию с Горячей клавиши неактивного окна


2-1178637823
likenoother
2007-05-08 19:23
2007.05.27
вывод текста через канвас





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский