Firebird : Trigger hangi koşullarda çalışır veya çalışmaz ?

Firebird ve Interbase veritabanları ve SQL komutlarıyla ilgli sorularınızı sorabilirsiniz. Delphi tarafındaki sorularınızı lütfen Programlama forumunda sorunuz.
Kullanıcı avatarı
mrmarman
Üye
Mesajlar: 4741
Kayıt: 09 Ara 2003 08:13
Konum: İstanbul
İletişim:

Firebird : Trigger hangi koşullarda çalışır veya çalışmaz ?

Mesaj gönderen mrmarman »

Merhabalar..

- Firebird'i kavramak için bir proje hazırlıyorum. İlk takıldığım nokta Trigger'ı devreye girip girmemesi konusu oldu.

- Paralel bir olay daha... DEFAULT tanımlanmış değerler de aynı durumla karşı karşıya.

- İlk olarak AutoIncremental artış yapmak üzere bir TRIGGER tanımı hazırladım. Tablo1 tablosunun T1_ID isimli alan adına yönelttim.

Kod: Tümünü seç

  with IBSQL do
    // TRIGGER - AutoInc
    try
      SQL.Clear;
      SQL.Add('CREATE TRIGGER AUTOINC FOR TABLO1');
      SQL.Add('ACTIVE BEFORE INSERT POSITION 0');
      SQL.Add('AS');
      SQL.Add('begin');
      SQL.Add('  if (NEW.T1_ID is null) then NEW.T1_ID=GEN_ID(GEN_AUTOINC, 1);');
      SQL.Add('end');
      Prepare;
      ExecQuery; 
    finally
      Close;
    end;
- Normalde girdi çıktıyı IBSQL ile yaptığım zaman -Trigger'a bağladığım T1_ID alanını hariç tutarak- aşağıdaki örnek gibi INSERT INTO işlemi yaparsam, Trigger görev yapıyor ve değer ataması yapıyor. Buraya kadar tamam.

Kod: Tümünü seç

  With DataModule1.IBSQL1 do // Trigger'ler çalışıyor...
  begin
    SQL.Clear;
    SQL.Add('Insert Into TABLO1');
    SQL.Add('   (KELIME, RESIM, SES, ANIME)');
    SQL.Add(' values');
    SQL.Add('   (:KELIME, :RESIM, :SES, :ANIME)');
    ParamByName('KELIME').Value := 'a';
    ParamByName('RESIM').Value := 'b';
    ParamByName('SES').Value := 'c';
    ParamByName('ANIME').Value := 'd';
    ExecQuery;
  end; //With
- Soruna gelince; TDBGrid'e bir TDataSource ile yansıtılmış IBDataset'de açık olan bu tabloda yeni bir kaydı aşağı ok ile eklediğimizde bu Trigger çalışmıyor. Yani otomatik artan rakam vermiyor. Halbu ki IBDataSet'in InsertSQL tanımı IBSQL'deki gibi tanımlandı ve ilgili alan hariç tutuldu.

- IBDataSet'in InsertSQL tanımı aşağıdaki gibidir...

Kod: Tümünü seç

With DataModule1.IBDataset1 do
  begin
    InsertSQL.Clear;
      InsertSQL.Add(' insert into TABLO1');
    //InsertSQL.Add('   (T1_ID, KELIME, RESIM, SES, ANIME)');
      InsertSQL.Add('   (KELIME, RESIM, SES, ANIME)'); // T1_ID Hariç tutuldu.
      InsertSQL.Add(' values');
    //InsertSQL.Add('   (:T1_ID, :KELIME, :RESIM, :SES, :ANIME)');
      InsertSQL.Add('   (:KELIME, :RESIM, :SES, :ANIME)');
  end;
- Normal bir projede bu şekilde TDBGrid'den kontrolsüz girişe izin vermem ama sebebini merak ediyorum.

- Bilgisini paylaşacaklara şimdiden teşekkürler..
Resim
Resim ....Resim
doganzorlu
Kıdemli Üye
Mesajlar: 395
Kayıt: 22 Tem 2004 09:15
Konum: İzmir
İletişim:

Mesaj gönderen doganzorlu »

Selam,

IBDataset den muhtemelen TID null gitmiyordur, 0 gidiyor olabilir. Trigger çalışıyor lakin;

Kod: Tümünü seç

if (NEW.T1_ID is null) then NEW.T1_ID=GEN_ID(GEN_AUTOINC, 1);
kontrolünde takılıyordur.[/code]
Doğan Zorlu, İzmir

------------------------
"Bu Kitap'ı sana yalnız şunun için indirdik: Hakkında ayrılığa düştükleri şeyi onlara iyice açıklayasın ve Kitap, iman eden bir topluluk için kılavuz ve rahmet olsun." (NAHL 64)
Kullanıcı avatarı
mrmarman
Üye
Mesajlar: 4741
Kayıt: 09 Ara 2003 08:13
Konum: İstanbul
İletişim:

Mesaj gönderen mrmarman »

Tekrar merhaba....

- T1_ID için atanan değer 0 değil NULL olduğu için hata alıyorum. 0 olsa kabul edecekti.

- En az bir kayıt olsun deyip burayı elimle girersem kayıt başarılı oluyor ama bir sonraki kayıtta yine null kalıyor...

- Hatta Trigger olmayan bir alan olarak deneme amaçlı eklediğim SECENEK diye bir alan daha var en sonda. Default değer olarak 'h' alması gerekiyor. O dahi default değerini almayıp NULL kalıyor... Halbu ki IBSQL ile bu değer de default değerine kavuşuyor.

- Dediğim gibi IBSQL ile aynı INSERT INTO satırları çalışırken, IBQuery +IBUpdate veya daha zaten aynı anlama geldiği için sonradan dönüştürdüğüm IBDataSet ile değer almıyor. SECENEK dahi Default değer almıyor.

- Ek olarak bildireyim, EMS (EMS Interbase Firebird Manager 3) ile DATA girişi için tablonun DBGrid'inde elle DATA girişi yaparken hem Trigger çalışıyor hem de default değer.

- Örnek Veritabanı : http://divxturk.divxforever.com/files/g ... ericat.zip

Tablo1 Structure aşağıdaki şekide...

Kod: Tümünü seç

const
  Tablo = 'Tablo1';
begin
 { --- Table Structure --- }
  With KomutListesi do
  begin
    Clear;
    Add( 'CREATE TABLE ' + Tablo + ' (');
    Add( '  T1_ID      NUMERIC NOT NULL,');
    Add( '  KELIME     VARCHAR (50) CHARACTER SET WIN1254 COLLATE PXW_TURK,');
    Add( '  RESIM      VARCHAR (50) CHARACTER SET WIN1254 COLLATE PXW_TURK,');
    Add( '  SES        VARCHAR (50) CHARACTER SET WIN1254 COLLATE PXW_TURK,');
    Add( '  ANIME      VARCHAR (50) CHARACTER SET WIN1254 COLLATE PXW_TURK,');
    Add( '  SECILI     CHAR    (01) CHARACTER SET NONE DEFAULT ''h'' COLLATE NONE,');
    Add( 'Primary Key ("T1_ID")' );
    Add( ')' );
  end;
end;
Resim
Resim ....Resim
bukentay
Üye
Mesajlar: 44
Kayıt: 16 Şub 2004 07:21

Mesaj gönderen bukentay »

hata veriyordan kastiniz T1_ID alani otomatik deger almiyor ise yolladiginiz veritabanini indirip denedim. aslinda deger aliyor ama aldigi deger grid de gozukmuyor.eger veriyi girdikden sonra commit ediyorsaniz, programi acip kapadikdan sonra T1_ID alaninin degeri gozukuyor.
ayni sorun beni bir hayli ugrastirmisti, verileri grid haricinde de girseniz dataseti kapatip acmadan otomatik artan alan degeri gozukmuyordu bir turlu.otomatik alan isini datasetin generatorfield kismindan yapinca sorun hallolmustu..
Kullanıcı avatarı
mrmarman
Üye
Mesajlar: 4741
Kayıt: 09 Ara 2003 08:13
Konum: İstanbul
İletişim:

Mesaj gönderen mrmarman »

@bukentay yazdı:hata veriyordan kastiniz T1_ID alani otomatik deger almiyor ise yolladiginiz veritabanini indirip denedim. aslinda deger aliyor ama aldigi deger grid de gozukmuyor.eger veriyi girdikden sonra commit ediyorsaniz, programi acip kapadikdan sonra T1_ID alaninin degeri gozukuyor.
ayni sorun beni bir hayli ugrastirmisti, verileri grid haricinde de girseniz dataseti kapatip acmadan otomatik artan alan degeri gozukmuyordu bir turlu.otomatik alan isini datasetin generatorfield kismindan yapinca sorun hallolmustu..
- Veritabanını nerede denediniz. Delphi projesinde bir DBGrid'de denemenizi salık veririm.

- Sizin projede Dataseti kapatıp açmadan aldığı değeri görememenize rağmen, kayıt işlemi başarılı oluyordu değil mi ? Unique değer veya Null kaldı hatası almıyordunuz. Buradaki sorunda durum farklı. DBGrid - IBDataSet'e bağlıyken Trigger hiç çalışmıyor. :!:

- EMS, IBManager gibi programlar bildiğim kadarıyla Trigger ve/veya Generator varsa olayları veritabanı cephesinde bırakmayıp manuel olarak takibe alıyorlar...

- Generatorfield ile zaten sorun kalmıyor. Bırakın orayı biliyorsunuz Table'ın beforepost olayında dahi çözüm çocuk oyuncağı :idea: ama amacım Firebird'in Delphi cephesi değil, veritabanı cephesinde çözüm üretmeyi öğrenmek. Zaten doğal olarak bugüne kadar hep Delphi cephesinde program geliştirdim.

- SECILI alanının Default değer almayışına nasıl bir anlam veriyorsunuz ? O da benzeri bir durum.
Resim
Resim ....Resim
bukentay
Üye
Mesajlar: 44
Kayıt: 16 Şub 2004 07:21

Mesaj gönderen bukentay »

ben FIBPlus kullandigim icin sizin soylediginiz hatayi almiyormusum.
standart ibx componentleri kullaninca dediginiz gibi T1_ID alani icin deger girmelisiniz diye hata verdi.
bunu halletmek icin T1_ID alaninin FieldKind ozelligini ftInternalCalc yapmaniz lazim. o zaman grid icinden bilgi girerken sorun cikarmiyor.fakat bu seferde alanin yeni degeri dataseti kapatip acmadan gridde gozukmuyor.
doganzorlu
Kıdemli Üye
Mesajlar: 395
Kayıt: 22 Tem 2004 09:15
Konum: İzmir
İletişim:

Mesaj gönderen doganzorlu »

Selam,

Beforepost da nasıl çözüyorsunuz olayı acaba ? Bu konuda kullandığınız metodu paylaşabilir misiniz ?
Doğan Zorlu, İzmir

------------------------
"Bu Kitap'ı sana yalnız şunun için indirdik: Hakkında ayrılığa düştükleri şeyi onlara iyice açıklayasın ve Kitap, iman eden bir topluluk için kılavuz ve rahmet olsun." (NAHL 64)
Kullanıcı avatarı
mrmarman
Üye
Mesajlar: 4741
Kayıt: 09 Ara 2003 08:13
Konum: İstanbul
İletişim:

Mesaj gönderen mrmarman »

@bukentay
- Haklı olabilirsiniz. IBX standart bileşenleri veritabanından yeterince feedback alamıyor olabilir.

@doganzorlu yanlış anladınız herhalde. Soru şeklinizden sanki before post'ta sihirli bir komutla Trigger tetikleyeceğim gibi bir şey anladığınızı sezinledim... :lol:

- BeforePost'ta Null kontrolü yapıp null olanlara ilk değer vererek ve paralel bir SQL ile son kaydı okuyup generatordeki tutulan sayı gibi olmasa da bir fazlasını vererek tabii ki 8)
Resim
Resim ....Resim
doganzorlu
Kıdemli Üye
Mesajlar: 395
Kayıt: 22 Tem 2004 09:15
Konum: İzmir
İletişim:

Mesaj gönderen doganzorlu »

Selam,

Doğru anlamışım demekki.. Son numarayı bul bir artır çözümü, çok kullanıcılı ve yüksek yoğunluklu talolarda çakışmayla sonuçlanacağı için yöntem olarak tercih edilmemelidir. Bu noktada FB içinde bir SP hazırlayıp , size bir Generator den alacağı id yi vermesini sağlamalısınız.

Yani id null ise SP yi çağır, (misal stok hareket için get_new_id('stok_hareket')) değeri id ye koy kaydet.. En buyuk numara, tek kullanıcı olduğunda %100 güvenlidir. Ama bunun dışında güvenilmezdir.

Kolay gelsin,
Doğan Zorlu, İzmir

------------------------
"Bu Kitap'ı sana yalnız şunun için indirdik: Hakkında ayrılığa düştükleri şeyi onlara iyice açıklayasın ve Kitap, iman eden bir topluluk için kılavuz ve rahmet olsun." (NAHL 64)
Kullanıcı avatarı
mrmarman
Üye
Mesajlar: 4741
Kayıt: 09 Ara 2003 08:13
Konum: İstanbul
İletişim:

Mesaj gönderen mrmarman »

- Zaten sorun da burada hocam... otomatik değer almaması. DBGrid ile satır kayıt eklendiğinde bu olmuyor. :idea:

- ID alanına göre sıralı son kaydı okuma doğru kullanıldığında bence güvenlidir. BeforePost olayında yapılıyor çünkü. Baştan rakam verip beklenmiyor... Zaten Try Except bloğu olmadan Post etmek (network veritabanı erişimi kapanması vb durumlar için) doğru olmazdı değil mi...

- Buna göre IB için söylüyorum Generator de güncellenmeli tabii.

// Neyse bu aşamada vakit kaybına gerek yok //

- Generator ile nasıl halledildiğini merak eden olursa diye yazıyorum, ama ben bu şekilde bir çözümden değil, sadece TIBSQL ile veritabanına etki yapmayı tercih edicem. Trigger'ların sağlığı için sanıyorum bu şart.

Kod: Tümünü seç

  With DataModule1.IBDataset1.GeneratorField do
  begin
    Field       := 'T1_ID';
    Generator   := 'GEN_AUTOINC';
    IncrementBy := 1;
    ApplyEvent  := gamOnPost;
  end;
- DBGrid'i yapmam gerektiği gibi readonly yapıp TEdit'lere aldığım veriyi TIBSQL ile INSERT INTO edicem. Bu sayede tüm Trigger ve Default'lar çalışacak.

- Hala merakım devam ediyor. Önerisi/konu hakkında bilgisi olanlar varsa lütfen yazsın...
Resim
Resim ....Resim
Kullanıcı avatarı
mrmarman
Üye
Mesajlar: 4741
Kayıt: 09 Ara 2003 08:13
Konum: İstanbul
İletişim:

Mesaj gönderen mrmarman »

Herkese duyurulur... Çözüm üretmeyi başardım...
:lol: :lol: :lol: :lol: :lol:
@mrmcop yazdı:- ID alanına göre sıralı son kaydı okuma doğru kullanıldığında bence güvenlidir. BeforePost olayında yapılıyor çünkü. Baştan rakam verip beklenmiyor... Zaten Try Except bloğu olmadan Post etmek (network veritabanı erişimi kapanması vb durumlar için) doğru olmazdı değil mi...
- Son yazdığım mesajdaki şu cümleme bir daha bakınca zihnim aydınlanıverdi...

- DBGrid ile giriş yapılmasına müsade ettim ve beforepost olayında bu işlemi iptal ettirdim. İptal ettirmeden önce de IBSQL'e mevcut verileri aktardım. NULL kalması gereken alanları NULL bıraktım ve işte sonuç. Çalışıyor... Hem default değerler hem de Trigger'lar... 8)

Kod: Tümünü seç

procedure TForm2.IBDataSet1BeforePost(DataSet: TDataSet);
begin
  With DataModule1.IBSQL1 do // Trigger'ler çalışıyor...
  begin
    DataModule1.IBSQL1.Transaction := DataModule1.IBTransaction1;
    DataModule1.IBSQL1.Database    := DataModule1.IBDatabase1;
    SQL.Clear;
    SQL.Add('Insert Into TABLO1');
    SQL.Add('   (KELIME, RESIM, SES, ANIME)');
    SQL.Add(' values');
    SQL.Add('   (:KELIME, :RESIM, :SES, :ANIME)');
    ParamByName('KELIME').Value := DataModule1.IBDataSet1.FieldByName('KELIME').AsString;
    ParamByName('RESIM').Value  := DataModule1.IBDataSet1.FieldByName('RESIM').AsString;
    ParamByName('SES').Value    := DataModule1.IBDataSet1.FieldByName('SES').AsString;;
    ParamByName('ANIME').Value  := DataModule1.IBDataSet1.FieldByName('ANIME').AsString;
    DataModule1.IBDataSet1.Cancel;
    ExecQuery;
  end; //With
  If DataModule1.IBTransaction1.InTransaction
    then DataModule1.IBTransaction1.CommitRetaining;
  Application.ProcessMessages;
  DataModule1.IBDataSet1.Active := False;
  DataModule1.IBDataSet1.Active := True;
  Abort;
end;
Resim
Resim ....Resim
doganzorlu
Kıdemli Üye
Mesajlar: 395
Kayıt: 22 Tem 2004 09:15
Konum: İzmir
İletişim:

Mesaj gönderen doganzorlu »

Selam,

Sanırım tam ifade edemedim. Son olarak belirtmek isterim ki, sadece beforepost içinden bir SP aracılığıyla bir GENERATOR kullarak id alıp işinizi görebilirsiniz. Son numara yerine generatorden alacaksınız numarayı hepsi bu. Böylelikle DataBound kontrolleri de olması gerektiği gibi kullanmaya başlayabilirsiniz. Bu çalışıyor dediğiniz yöntemle içinde onlarca field bulunan tablolarda nasıl çalışacaksınız ? Her seferinde dataset i refresh ederseniz oluşacak network trafiğiyle nasıl başa çıkacaksınız ? Bu şekilde bir çözüm çözüm değil. Ama yine de karar sizin tabi ki....

İllaki true/false la dataseti refresh eden bir metod kullanacaksanız, id alanından sıfır gönderip (null değil, böylece contraint lere yakalanmazsınız) trigger içinde de null değil sıfır ı kontrol ederek değer atayın.. Böylece dataseti refresh ettiğinizde hem defualt değerler hem de id databound controller içinde görünecektir. Araya yazdığınız değişikliği iptal et/SQL ile insert et bölümünden kurtulmuş olursunuz...

Kalın sağlıcakla,
Doğan Zorlu, İzmir

------------------------
"Bu Kitap'ı sana yalnız şunun için indirdik: Hakkında ayrılığa düştükleri şeyi onlara iyice açıklayasın ve Kitap, iman eden bir topluluk için kılavuz ve rahmet olsun." (NAHL 64)
Kullanıcı avatarı
mrmarman
Üye
Mesajlar: 4741
Kayıt: 09 Ara 2003 08:13
Konum: İstanbul
İletişim:

Mesaj gönderen mrmarman »

Selam...

- Generator'den okuma fikrine katılıyorum. Otomatik artan rakamlar için ideal olabilir ama sonuçta bu rakamı okuyup yerine yenisini koymak için de Delphi'de kod yazmak gerekecek.

- İşi tamamen bedavaya getirmeye niyetim yok ama asıl konu IBSQL ile IBDataset veya IBQuery+IBUpdateSQL aynı SQL satırlarına rağmen neden farklı davranıp tetikleme görevlerini ifa edemiyorlar... Asıl sorun burada. Buna dair bir fikriniz var mı öğrenmek isterdim...

- Dediğim gibi DBGrid'den direkt veri girişine normalde zaten izin vermem. Çözüm budur demek illaki bunu kullanıcam veya hekes bunu kullansın anlamına gelmiyor. Eldeki kuş daldaki kuş olayı anlayacağınız.

- Table listelemiyoruz. DBGrid'de listelenecek kadar dar bir SQL sorgunun network trafiğindeki etkisini büyütmemek lazım. Buradaki asıl konu default değerlerin alınabilmesi ve trigger, generator ve SP'lerin çalışır halde olması.
@doganzorlu yazdı:İllaki true/false la dataseti refresh eden bir metod kullanacaksanız, id alanından sıfır gönderip (null değil, böylece contraint lere yakalanmazsınız) trigger içinde de null değil sıfır ı kontrol ederek değer atayın.. Böylece dataseti refresh ettiğinizde hem defualt değerler hem de id databound controller içinde görünecektir. Araya yazdığınız değişikliği iptal et/SQL ile insert et bölümünden kurtulmuş olursunuz...
- Bir de DBGrid'e değer yansıtabilen IBQuery veya IBDataset',in SP'lerin çalışacağının garantisi nedir ? Ben şimdi deniycem ama ümitli değilim...
Resim
Resim ....Resim
Kullanıcı avatarı
miskin
Üye
Mesajlar: 103
Kayıt: 26 Tem 2005 02:02
Konum: Gavuristan

Mesaj gönderen miskin »

soruna tam cevap degil, buna ragmen.
Ben benzeri bir sorunla karsilastigimda. IBConsole ve Programi design modusta calistirip Delphi'nin Debugger'ini Kullandim.
Trigger davranisinin nasil oldugunu bulduydum. Ama niye öyle calistigini anlamadiydim.
Degisiklikleri triggerle baska bir tabloya yaziyordum.
miskin
Ve Tanri, bütün kullarini davul edecek :)
doganzorlu
Kıdemli Üye
Mesajlar: 395
Kayıt: 22 Tem 2004 09:15
Konum: İzmir
İletişim:

Mesaj gönderen doganzorlu »

Selam,
İşi tamamen bedavaya getirmeye niyetim yok ama asıl konu IBSQL ile IBDataset veya IBQuery+IBUpdateSQL aynı SQL satırlarına rağmen neden farklı davranıp tetikleme görevlerini ifa edemiyorlar... Asıl sorun burada. Buna dair bir fikriniz var mı öğrenmek isterdim...
IBDataSet adından da anlaşılacağı gibi verinin çift yönlü aktarımı için çalışır. İçinde field collection ve buna bağlı client-side constraint ler barındırır. UpdateSQL ise bunları barındırmaz vereceğiniz DML i çalıştırır. Yani verinin prezentasyonu için IBUpdateSQL i kullanamazsınız bu nedenle. Adım adım ne olduğuna bakalım;

IBDataSet;

1. Design time DataSet i oluşturduğunuzda, db den db constraintlerine uygun şekilde field listi oluşturur. Elle değiştirme hakkınız her zaman vardır. Post etmeye kalkışıldığında, DB den önce buradaki constraint ler çalışacaktır.

2. Active ettiniz... Filtreye uygun kayıtlar geldi.

3. Yeni kayıt eklediniz DB ye birşey gitmedi ve oradan da default değerler gelmedi.. DB etkileşimi sadece post/delete/activate durumlarında çalışır.

4. Post ettiniz. Öncelikle client-side constraintler değerlendirildi. Not null alan var ve böyle göndermeye kalktınızsa daha DB ye gidemeden engellendiniz. Diyerlim ki burayı geçtiniz.. DB ye veriler gönderildi, sonuç pozitifse kaydedildi dedi ve bitti. Farkettiniz mi ? DB den geri bilgi gelmedi... DB tarafındaki default larınız ve varsa trigger la değiştirdiğiniz alanlar buraya yansımadı ve şu anda bir ekranda gördüğünüz bilgiler bir de DB de bulunanlar olarak aynı kaydın iki versiyonu elinize geçti..

5. Active false yaptınız, resetlendi.

6. Active true yaptınız, değerler DB den tekrar geri geldi.. Trigger tarafından değiştirildiği haliyle.. Default lar da geldi..

Bunu nasıl engellersiniz ..? Multiuser kullanımlarda ortak payda olan primary key, yani buradaki ID yi beforepost a yazacağınız bir satırlık bir ifade ile DB den "generator kullanarak" alırsınız. Default değerleri, DataSet de de set edersiniz. Burada yapıyorsam bir de DB ye neden yapıyorum demeyin. Oraya birisi başka bir kaynaktan veri insert ederse DB stabilitesi için gerekli olacaktır. Üstelik ID nin boş olması durumunda bir ID verme işlemi de mutlaka bulunmalıdır.

Bu şekilde active true/false yapmadan ekranla db deki değerlerin eşlenik olmasını sağlarsınız.

Gelelim UpdateSQL e,

1. DesignTime create. Hiçbirşey yapmazz.
2. SQL i içine yaz ve Exec ettir.. Bu durumda verdiğiniz SQL çalıştırılır ve sonuç bildirilir.. Hepsi bu... Veriyi bununla prezente etmediğiniz için başkaca birşey yapmak gerekmez.

Sizin anlayacağınız eğer Dataset i kullanıyor ve client-side constraint leri geçemiyorsanız, DB ile etkileşmediğinizden trigger lar çalışmaz. Öncelikle bu iki katmanı farketmelisiniz. Eğer client-side constraint lerden geçebilir de DB ye kadar gidebilirseniz emin olun trigger mutlaka çalışacaktır.

Aradaki farkı anladığınızı umuyorum....

Kolay gelsin,
Doğan Zorlu, İzmir

------------------------
"Bu Kitap'ı sana yalnız şunun için indirdik: Hakkında ayrılığa düştükleri şeyi onlara iyice açıklayasın ve Kitap, iman eden bir topluluk için kılavuz ve rahmet olsun." (NAHL 64)
Cevapla