Firebird'de değişen değerleri yeni bir tabloya yazma

Firebird ve Interbase veritabanları ve SQL komutlarıyla ilgli sorularınızı sorabilirsiniz. Delphi tarafındaki sorularınızı lütfen Programlama forumunda sorunuz.
Cevapla
name
Kıdemli Üye
Mesajlar: 243
Kayıt: 09 Ağu 2003 02:11
Konum: İstanbul

Firebird'de değişen değerleri yeni bir tabloya yazma

Mesaj gönderen name »

Merhaba

Arkadaşlar 2 tablom var. Birinci tabloda hangi field'larda değişiklik yapıldıysa ikinci tabloya bu field adı ve yeni değeri yazılmalıdır.

Birinci trigger ile bu işlemi yapıyorum ama çok büyük bir trigger ortaya çıkıyor ve yeni field'lar eklendikçe sorun yaşatacak bir yapı oluşuyor.

Kod: Tümünü seç

CREATE OR ALTER TRIGGER VALUES_TABLE_AFTER_UPD FOR VALUES_TABLE
ACTIVE AFTER UPDATE POSITION 0
AS
begin
  if (old.field1<>new.field1) then
    insert into MODIFIED_VALUES (VALUES_TABLE_ID, MODIFIED_TIME, FIELD_NAME, NEW_VALUE) VALUES (new.ID, current_timestamp, 'field1', new.field1); 

  if (old.field2<>new.field2) then
    insert into MODIFIED_VALUES (VALUES_TABLE_ID, MODIFIED_TIME, FIELD_NAME, NEW_VALUE) VALUES (new.ID, current_timestamp, 'field2', new.field2); 
  ...
  .....
  ...
  if (old.field100<>new.field100) then
    insert into MODIFIED_VALUES (VALUES_TABLE_ID, MODIFIED_TIME, FIELD_NAME, NEW_VALUE) VALUES (new.ID, current_timestamp, 'field100', new.field100); 
end
İkinci trigger tam olarak işimi görüyor ama oda çalışmıyor. Değişken kullanarak "new.<variable>" ve "old.<variable>" değerlerini nasıl alırım? Yani dinamik bir şekilde "old. || field_name" gibi bir ifade kullanarak eski ve yeni field değerlerini almak istiyorum.

Kod: Tümünü seç

CREATE OR ALTER TRIGGER VALUES_TABLE_AFTER_UPD FOR VALUES_TABLE
ACTIVE AFTER UPDATE POSITION 0
AS
declare variable field_name DOMAIN_VC50;
declare variable old_value DOMAIN_DOUBLE;
declare variable new_value DOMAIN_DOUBLE;
begin
  for select rdb$field_name from rdb$relation_fields
    where RDB$RELATION_NAME='VALUES_TABLE' and RDB$FIELD_SOURCE='DOMAIN_DOUBLE' into field_name
  do
    begin
      --Execute Statement 'select old.' || field_name || ' from rdb$relation_fields' INTO :old_value;  --çalışmıyor
      --Execute Statement 'select new.' || field_name || ' from rdb$relation_fields' INTO :new_value;  --çalışmıyor

      Execute Statement 'old.' || field_name INTO :old_value;  --çalışmıyor
      Execute Statement 'new.' || field_name INTO :new_value;  --çalışmıyor

      if (old_value<>new_value) then
        insert into MODIFIED_VALUES (VALUES_TABLE_ID, MODIFIED_TIME, FIELD_NAME, NEW_VALUE) VALUES (new.ID, current_timestamp, :field_name, :new_value);
    end
end
Kullanıcı avatarı
freeman35
Admin
Mesajlar: 2380
Kayıt: 12 Haz 2003 04:05
Konum: merkez camii yanı

Re: Firebird'de değişen değerleri yeni bir tabloya yazma

Mesaj gönderen freeman35 »

Trigger ın büyük olmasında sıkıntı çıkmaz çıkarsada 2-3 parçaya bölebilirsin, tek trigger olmak zorunda değil.
Bu yöntemle bende log tutuyorum, firebird 1.5 field tiplerinde sıkıntı yaşamamak için değerleri varchar yapmıştım. FB 2.5.3 için ikinci db ye kaydetmeyi biraz araştırmıştım, başka bir iş çıkınca araştırmayı bırakmak zorunda kalmıştım.
Bu konu hakkında bilgisi olan varsa paylaşırsa sevinirim
ZAGOR TENAY TÜRK'tür... TÜRK kalacak...
Zoru başarırım, İmkansız zaman alır
FreeMan 35.5

Soru sormaya üşenmiyorsan, sorunun çözümünü yazmaya da üşenme !!!
name
Kıdemli Üye
Mesajlar: 243
Kayıt: 09 Ağu 2003 02:11
Konum: İstanbul

Re: Firebird'de değişen değerleri yeni bir tabloya yazma

Mesaj gönderen name »

Mecbur kalırsam (ki öyle görünüyor) birinci yöntem ile işimi halledicem :) Ancak birinci yöntem hataya açık bir yapıda. "VALUES_TABLE" tablosuna yeni alanlar eklendiğinde trigger'ı güncellemeyi unuttuğumu düşünün yada yanlış güncellediğimi. Sonra debug yap dur :) Az ve öz kodlama yapmaya çalışmışımdır her zaman.

Bilindiği gibi "old" ve "new" context variable'lardır. "rdb$get_context" function'u belki işimi görür dedim ama yemedi :) null değer dönüyor. Firebird'de "old ve new" context'lerinin bu şekilde kullanımları yok galiba.

Kod: Tümünü seç

old_value=rdb$get_context('USER_TRANSACTION', 'old.' || field_name);  --çalışmıyor
Birde http://www.firebirdfaq.org/faq133/ link'inde en alttaki kod bir an için beni umutlandırdı. Ama hiç bir pratik kullanımı yok ve sorunun cevabı bu değil. Ne saçmalamışlar acaba? Yada sundukları çözümü ben anlamadım.

Kod: Tümünü seç

select 'if (new.' || rdb$field_name || ' is null and old.' ||
rdb$field_name || ' is not null or new.' || rdb$field_name ||
'is not null and old.' || rdb$field_name || ' is null or new.' ||
rdb$field_name || ' <> old.' || rdb$field_name || ') then'
from rdb$relation_fields
where rdb$relation_name = 'EMPLOYEE';
Cevapla