RAISERROR ve PRINT

MS SQL Server veritabanı ve SQL komutlarıyla ilgli sorularınızı sorabilirsiniz. Delphi tarafındaki sorularınızı lütfen Programlama forumunda sorunuz.
Kullanıcı avatarı
conari
Üye
Mesajlar: 2102
Kayıt: 27 Nis 2006 03:10
Konum: İstanbul & Gebze Karışık

RAISERROR ve PRINT

Mesaj gönderen conari »

Merhaba arkadaşlar, uzun zamandır aranızda değildim.. Biraz ara vermiştim bu işlere.
Şimdi şöyle bir sorum olacak.
SQL de bir Trigger yazdım ve duruma göre RAISERROR döndürüyorum, fakat bu işlemi durduruyor ben uyarı verip devam etmesini istiyorum. Program kodları vs bende olmadığı için bunu vtden yapabilirim. PRINT mesajı ile de olmadı. RAISde devam ettirme durumu yokmu dur?
:roll: Teşekkürler.
Bir kelimenin anlamını öğretsen bile yeter..
ResimResim
Kullanıcı avatarı
mussimsek
Admin
Mesajlar: 7586
Kayıt: 10 Haz 2003 12:26
Konum: İstanbul
İletişim:

Re: RAISERROR ve PRINT

Mesaj gönderen mussimsek »

Merhaba,

RiaseError dediğiniz gibi çalışıyor, uyarı verip devam etme gibi bir kullanım hiç duymadım.

Amacınız debug etmek ise bir tabloya insert ile istediğiniz verileri ekleyebilirsiniz. Kullanıcıyı durumdan haberdar etmek ise böyle birşey mümkün değil... Tam durumu, bir örnekle izah ederseniz belki farklı yorumlar, değişik yöntemler öneren çıkabilir.

Kolay gelsin.
Kullanıcı avatarı
conari
Üye
Mesajlar: 2102
Kayıt: 27 Nis 2006 03:10
Konum: İstanbul & Gebze Karışık

Re: RAISERROR ve PRINT

Mesaj gönderen conari »

Selam Hocam
Şöyle ki veri girişi yapılıyor. bende tablonun insert işlemine trigger yazım. girilen kodu kontrol ediyorum. Kod koşullara uyuyor ise RAIS yok ve işleme devam ediliyor, uymuyor ise ERROR mesajı veriyor ama tabloya kaydıda atmıyor.

Ben mesajı versin ama tabloya kaydıda atsın istiyorum.
Tşk.
Bir kelimenin anlamını öğretsen bile yeter..
ResimResim
thelvaci
Kıdemli Üye
Mesajlar: 770
Kayıt: 11 Tem 2010 07:17
Konum: Istanbul
İletişim:

Re: RAISERROR ve PRINT

Mesaj gönderen thelvaci »

Sql Server'ın hangi versiyonu ile çalışıyorsunuz bilmiyorum ama aslında Raiserror tam da istediğiniz şekilde çalışıyor maalesef. Bana kalırsa bu bir sorun, gerçek bir hata mekanizması değil. Neyse ki Sql Server 2012 'de gerçek bir hata mekanizmasını nihayet yapabildiler. throw ile yeni hata fırlatabiliyoruz ve gerçekten olması gerektiği gibi çalışıyor.

Kod: Tümünü seç

  RAISERROR('Deneme Hata Mesajı-1', 16, 1)
  PRINT 'Print Satırı-1'
  RAISERROR('Deneme Hata Mesajı-2', 16, 1)
  PRINT 'Print Satırı-2'
Yukarıdaki gibi bir kodda normalde (Delphi yada ona benzer dillerdeki exception mekanizması düşünüldüğünde) "Deneme Hata Mesajı-1" iletisini gördükten sonra başka bir şey görmememiz gerekir. Oysaki görüyoruz.! Sizde yeni bir Query penceresi açıp ilgili kodu oraya yapıştırarak test edebilirsiniz.

Benzer bir şekilde;

Kod: Tümünü seç

BEGIN TRY
	RAISERROR('Deneme Hata Mesajı-1', 16, 1)
	PRINT 'Print Satırı-1'
	RAISERROR('Deneme Hata Mesajı-2', 16, 1)
	PRINT 'Print Satırı-2'
END TRY
BEGIN CATCH
	RAISERROR('Begin Catch Hata Mesajı-1', 16, 1)
	PRINT 'Begin Catch Print Satırı-1'
	RAISERROR('Begin Catch Hata Mesajı-2', 16, 1)
	PRINT 'Begin Catch Print Satırı-2'
END CATCH
Yukarıdaki gibi bir kodda ise; aşağıdaki gibi bir sonuç ile karşılaşırsınız:

Msg 50000, Level 16, State 1, Line 8
Begin Catch Hata Mesajı-1
Begin Catch Print Satırı-1
Msg 50000, Level 16, State 1, Line 10
Begin Catch Hata Mesajı-2
Begin Catch Print Satırı-2

Görüldüğü üzere, BEGIN TRY içinde oluşan bir hata otomatikman BEGIN CATCH bloğuna dallanılmasına, ardından da ilgili satırların işletilmesine neden oluyor. Oysaki alışık olduğumuz exception yapısı bu şekilde işlemiyor. Normalde bir exception raise edildikten sonra altındaki satırların işletilmemesi gerekir. Bence bu hali ile Sql Server'da RaiseError kullanmak biraz dikkatli olmayı gerektiriyor. Çaresi ne mi; eğer Sql Server 2012 kullanıyorsanız throw anahtar sözcüğüne bakmalısınız derim.
Kullanıcı avatarı
mussimsek
Admin
Mesajlar: 7586
Kayıt: 10 Haz 2003 12:26
Konum: İstanbul
İletişim:

Re: RAISERROR ve PRINT

Mesaj gönderen mussimsek »

http://sqlhints.com/2013/06/30/differen ... ql-server/

@thelvaci, benden önce davranmış, biz hep goto ile dallandığımız için farketmedim ama raiseerror'dan sonraki satırlar çalışıyormuş zaten. Yukardaki linkte örnekler ve açıklamalar var.

Kolay gelsin.
Kullanıcı avatarı
conari
Üye
Mesajlar: 2102
Kayıt: 27 Nis 2006 03:10
Konum: İstanbul & Gebze Karışık

Re: RAISERROR ve PRINT

Mesaj gönderen conari »

Şuan 2005 kullanıyoruz ama yılbaşında 2012 ye geçeceğiz.
bu testi o zaman deneyim ben.

Tşk.
Bir kelimenin anlamını öğretsen bile yeter..
ResimResim
thelvaci
Kıdemli Üye
Mesajlar: 770
Kayıt: 11 Tem 2010 07:17
Konum: Istanbul
İletişim:

Re: RAISERROR ve PRINT

Mesaj gönderen thelvaci »

Şu an için ise Raiserror hata mesajını verdikten sonra RETURN kullanarak alt satırlara geçmesine engel olabilirsiniz. Böylece normal bir exception'ı simüle edebilirsiniz.
Kullanıcı avatarı
conari
Üye
Mesajlar: 2102
Kayıt: 27 Nis 2006 03:10
Konum: İstanbul & Gebze Karışık

Re: RAISERROR ve PRINT

Mesaj gönderen conari »

Hocam şöyleki,
Triggeri After inserte yazdım,
RAISERROR mesajı alınca, Rollback e düşüyor, veriyi vtye de yazmıyor.
Bu noktada mesajdan sonra yazmasını istiyorum
Bir kelimenin anlamını öğretsen bile yeter..
ResimResim
thelvaci
Kıdemli Üye
Mesajlar: 770
Kayıt: 11 Tem 2010 07:17
Konum: Istanbul
İletişim:

Re: RAISERROR ve PRINT

Mesaj gönderen thelvaci »

Bu durumda muhtemelen Raiserror kodu
Begin Try
End Try
Begin Catch
End Catch
blokları arasında yazımış gibi görünüyor. Böyle bir durumda elbette begin try içindeki bir raiserror begin catch bloğuna atlar ve muhtemelen de orada bir rollback transaction komutu vardır, o çalışıyordur.

Eğer durum bu şekilde ise Raiserror metodunu çağırmadan önce bir değişkeni set'leyerek Rollback çağrımının oluşmasını engelleyebilirsiniz. Tabii tam olarak düzgün bir yanıt verebilmemiz için sizin trigger'ı görmemiz gerekiyor. Ayrıca, Raiserror komutunun içindeki State parametresine bir göz gezdirmek isteyebilirsiniz ;) (Hani 16 geçtiğimiz kısım)
Kullanıcı avatarı
conari
Üye
Mesajlar: 2102
Kayıt: 27 Nis 2006 03:10
Konum: İstanbul & Gebze Karışık

Re: RAISERROR ve PRINT

Mesaj gönderen conari »

Trigger içeriği şöyleki;

AS
BEGIN
DECLARE...
...
....

BEGIN
SELECT .... FROM INSERTED
IF 1
BEGIN
IF 2
BEGIN
IF 3
BEGIN
SELECT @CT= COUNT(*) FROM X WHERE .........
IF( @CT =0)
BEGIN
RAISERROR ( 'Export platform ürün değil !!! Lütfen Ürünü kontrol ediniz. ',16, 1)
END
END
END
END
END
END
Bir kelimenin anlamını öğretsen bile yeter..
ResimResim
thelvaci
Kıdemli Üye
Mesajlar: 770
Kayıt: 11 Tem 2010 07:17
Konum: Istanbul
İletişim:

Re: RAISERROR ve PRINT

Mesaj gönderen thelvaci »

Gördüğümden anladığım kadarı ile trigger'ınız bir after trigger'ı. Dolayısı ile hata olduğunda otomatikman Rollback oluyor. After trigger'ı yerine kodunuzu Instead of Insert trigger'ında yazarsanız, istediğiniz kontrol olacaktır. Instead of Insert trigger'ını yazdığınızda Sql Server'a şöyle demiş oluyorsunuz: "Ey! Sql Server, kayıt girişi işini sen yönetme bu işi ben kontrol edeceğim." Daha kaba bir tabir ile, before Insert gibi çalışacaktır.

Dolayısı ile Instead of Insert trigger'ınızda gereken Insert Into.. kodunuzu da yazmayı unutmamanız gerekir ;)
Kullanıcı avatarı
conari
Üye
Mesajlar: 2102
Kayıt: 27 Nis 2006 03:10
Konum: İstanbul & Gebze Karışık

Re: RAISERROR ve PRINT

Mesaj gönderen conari »

Selam,
Dediğim gibi program kodları bende değil. INSERT komudunu program gönderiyor.
Bu durumda RAISERROR e düşen kayıtlar için INSERTED tablosundan kaydı alıp asıl tabloya kendim mi yazmam gerekiyor.
Böyle bir durumda KISIR döngüye girmez mi?
Bir kelimenin anlamını öğretsen bile yeter..
ResimResim
thelvaci
Kıdemli Üye
Mesajlar: 770
Kayıt: 11 Tem 2010 07:17
Konum: Istanbul
İletişim:

Re: RAISERROR ve PRINT

Mesaj gönderen thelvaci »

Merhaba, programın kodlarına ihtiyacınız yok şu aşamada. Dikkat ederseniz eğer; After yada daha bilinen ismi ile For triggerından bahsetmedim size; onun yerine Instead Of triggerı dedim. Bu trigger kayıt işlemi gerçekleşmeden önce tetiklenir ve kayıt etme yada etmeme sorumluluğu tamamen size bırakılır. Siz Instead of triggerında kayıt yapılmasına engel olacak kontrolleri yaparsınız, bu kontroller aşılır ise Insert into çağrımı ile kaydın yapılmasında bir sakınca olmadığını ifade edersiniz. Bundan sonra ise aynı tablo üzerindeki After triggerı devreye girer. Konuyu ziyadesi ile kavramak için bir kaç deneme yapmalısınız kanaatimce, o zaman her şey daha da netleşecektir.
Kullanıcı avatarı
conari
Üye
Mesajlar: 2102
Kayıt: 27 Nis 2006 03:10
Konum: İstanbul & Gebze Karışık

Re: RAISERROR ve PRINT

Mesaj gönderen conari »

Hocam anlattıklarında hiç bir sorun yok, trigger mantığı okeyde,
RAISERROR mesjından sonra şöyle bir cümle ile INSERTED den alıp insertmü etmeliyim.

INSERT INTO Tablo SELECT * FROM INSERTED WHERE SIRA=@KEYNO

IDENTITY_INSERT e takılacağım. bu tabloda 80 civarı field var.
Bir kelimenin anlamını öğretsen bile yeter..
ResimResim
thelvaci
Kıdemli Üye
Mesajlar: 770
Kayıt: 11 Tem 2010 07:17
Konum: Istanbul
İletişim:

Re: RAISERROR ve PRINT

Mesaj gönderen thelvaci »

Ah be güzel kardeşim, google'dan hiç bakmadın mı Instead of trigger'larına. Trigger mantığı ok demişsin ama tam olarak "ok" değil demek ki. Instead of trigger diyorum bak dikkat et lütfen, after trigger demiyorum. Instead of insert triggerı yazdığında; nereden olursa olsun ilgili tabloya bir insert işlemi gerçekleştirdiğinde bu instead of insert trigger'ına dallanılır. Ardından sen inserted içinden ilgili kayıtları okuyabilirsin. Inserted'ın içindeki kayıtlar tampon bir bellekteki kayıtlardır(Senin insert etmek istediğin kayıtlar), ancak bu kayıtlar henüz veritabanına fiziksel olarak yazılmamışlardır.! Çünkü yazma işini "ben üstleneceğim" demişsin Sql Server'a. Bu durumda, yapman gereken kontroller var ise yapacaksın ardından da insert into ile yeniden bir insert kodu yazacaksın ki kayıtlar gerçekten de fiziksel olarak kayıt altına alınsın. Ayrıca belirtmek isterim ki, veritabanı tasarımı kesinlikle yanlış demektir eğer o tabloda 80 tane alan var ise. Normalizasyon kurallarını es geçmiş kim tasarlamış ise ilgili tabloyu. Bu tabloda yüzbin/milyon mertebesinde kayıtlar oluştuğunda, ilgili tabloya ufacık bir update, insert, delete ve hatta select dahi inanılmaz zamanlar alacaktır. Çünkü çok fazla page fragmantasyon olacaktır. Nonclustered indexler için leaf'ler bile epey yer kaplayacaktır. Herneyse kısaca bir örnek vermeye çalışayım;

Kod: Tümünü seç

  ...
  ...
  IF EXISTS(
                 SELECT 1
                 FROM INSERTED
                 WHERE
                    Yasi > 150
                )
  BEGIN
    IF @@TRANCOUNT > 0 ROLLBACK TRANSACTION;

    RAISERROR('Yaş 150 den büyük olamaz.!', 16, 1)
    RETURN;   
  END

  -- Yukarıdaki gibi daha pek çok kayıt öncesi kontrol işlemi yaptığınızı düşünelim.

 -- Hiç bir sorun yok, kayıt kaydedilebilir durumda.
  BEGIN TRY
    INSERT INTO Personel(Adi, Soyadi, Yasi)
    SELECT
      Adi,
      Soyadi,
      Yasi
    FROM INSERTED
  END TRY
  BEGIN CATCH
    IF @@TRANCOUNT > 0 ROLLBACK TRANSACTION;
    -- Hatayı bir yerlere kaydet ve yeniden raise et..
    RETURN
  END CATCH

  IF @@TRANCOUNT > 0 COMMIT TRANSACTION;
gibi kısaca..
conari yazdı:Hocam anlattıklarında hiç bir sorun yok, trigger mantığı okeyde,
RAISERROR mesjından sonra şöyle bir cümle ile INSERTED den alıp insertmü etmeliyim.

INSERT INTO Tablo SELECT * FROM INSERTED WHERE SIRA=@KEYNO

IDENTITY_INSERT e takılacağım. bu tabloda 80 civarı field var.
Cevapla