TETİKLEYİCİLER ve HATA KONTROLÜ 11.DERS TETİKLEYİCİLER ve HATA KONTROLÜ BUKET DOĞAN
Haftanın Hedefi Insert, Update, Delete tetikleyicilerini yazabilme ve daha önceki haftalarda öğrenilen karar yapıları, döngü yapılarını, kullanıcı tanımlı fonksiyonları kullanabilme Hata kontrolü yapabilme
Hatırlatma:Tetikleyici Nedir SQL de bir tabloda herhangi bir işlem yapıldığı anda otomatik olarak aynı tabloda veya başka bir tabloda başka işlemlerinde yapılmasını istediğimiz zamanlarda, Trigger'lar yapılmasını istediğimiz bu işlemi bizim adımıza otomatik olarak gerçekleştirirler. create trigger Isim on TabloAdi for Insert, Update, Delete (Tek tek veya hepsi birden yazılabilir) as islemler
Soru Personeller tablosunda yapılacak unvan değişimlerinde(güncellemelerinde) Eskigörevler isimli bir tabloya personelin Id, isim ve eski görevi, görev değişim tarihi ve yeni görevi bilgilerini yazan bir trigger yazınız.
Örnek CREATE TRIGGER [dbo].[TrigDegisimTarihi] ON [dbo].[Personeller] AFTER UPDATE AS declare @Personel int SELECT @Personel = PersonelID FROM inserted UPDATE Personeller SET IslemTarihi = GETDATE() WHERE Personeller.PersonelID = @Personel --Değişken tanımlamadan da yapılabilir: FROM inserted WHERE Personeller.PersonelID = inserted.PersonelID
Örnek CREATE TRIGGER [dbo].[UYGULAMA] ON [dbo].[Personeller] AFTER UPDATE AS declare @eski varchar(30),@yeni varchar(30), @idsi integer select @idsi= PersonelID from inserted SELECT @eski = Unvan FROM deleted SELECT @yeni = Unvan FROM inserted IF @eski<>@yeni Begin INSERT INTO EskiPersonel (PersId ,EskiUnvan, YeniUnvan, islemtarihi) VALUES (@idsi, @eski, @yeni, GETDATE()) END
Tabloları oluşturma CREATE TABLE Musteri_Demo( mus_ID int identity, mus_isim varchar(55), mus_maas decimal (10,2)) Insert into Musteri_Demo values ('Ahmet',1000); Insert into Musteri_Demo values ('Münir',1200); Insert into Musteri_Demo values ('Avni',1100); Insert into Musteri_Demo values ('Mansur',1300); Insert into Musteri_Demo values ('Rehan',1400); create table Musteri_Demo_Audit ( mus_ID int, Mus_maas decimal(10,2), Audit_Action varchar(100), Audit_Timestamp datetime )
CREATE TRIGGER [dbo]. [trgAfterInsert] on [dbo] CREATE TRIGGER [dbo].[trgAfterInsert] on [dbo].[Musteri_Demo] FOR INSERT as declare @Musid int, @Musisim varchar(55), @Musmaas decimal(10,2), @audit_action varchar(100); select @Musid=i.Mus_ID from inserted i; select @Musisim=i.Mus_İsim from inserted i; select @Musmaas=i.Mus_Maas from inserted i; set @audit_action='Girilen Kayıt -- After Insert Trigger.'; insert into Musteri_Demo_Audit(Mus_ID,Mus_İsim,Mus_Maas,Audit_Action,Audit_Timestamp) values (@Musid,@Musisim,@Musmaas,@audit_action,getdate()); PRINT 'AFTER INSERT trigger devreye girdi.‘ insert into Musteri_Demo(Mus_İsim,Mus_Maas)values ('SÜLEYMAN',1000);
CREATE TRIGGER trgAfterDelete ON dbo CREATE TRIGGER trgAfterDelete ON dbo.Musteri_Demo FOR DELETE AS declare @Musid int, @Musisim varchar(55), @Musmaas decimal(10,2), @audit_action varchar(100); select @Musid=d.Mus_ID FROM deleted d; select @Musisim=d.Mus_İsim from deleted d; select @Musmaas=d.Mus_Maas from deleted d; select @audit_action='Silinen -- After Delete Trigger.'; insert into Musteri_Demo_Audit (Mus_ID,Mus_İsim,Mus_Maas,Audit_Action,Audit_Timestamp) values (@Musid,@Musisim,@Musmaas,@audit_action,getdate()); PRINT 'AFTER DELETE TRIGGER devreye girdi.‘ DELETE FROm Musteri_Demo where mus_Id = 5
Try Catch Programlama dillerinde oldugu gibi t-sql de de try catch bloklari olusan hatayi yakalamamizi saglar ve olusan hata hakkinda bilgi sahibi olmamiza imkan verir. TRY CATCH kullanildiginda, bir hata olustugu zaman bu hata istemciye geri döndürülmez, hata CATCH blogu içinde islenir.
Try Catch Yapısı BEGIN TRY Hata olabilecek kod bloğu END TRY BEGIN CATCH Eğer hata olursa hatanın yakalandığı kısım. END CATCH
BEGIN TRY SELECT a = 1 SELECT b = 1/0 SELECT c = 3 END TRY BEGIN CATCH PRINT 'Hata Mesaji' END CATCH
Hatalar CATCH blogu içinde kullanabilecegimiz ve olusan hata hakkinda bilgi alabilecegimiz bir çok fonksiyon var. BEGIN TRY SELECT Sonuc = 5/0 END TRY BEGIN CATCH SELECT [Hata_Satiri] = ERROR_LINE(), [Hata_Sayisi] = ERROR_NUMBER(), [Hata_Onemi] = ERROR_SEVERITY(), [Hata_Durumu] = ERROR_STATE() SELECT [Hata_Mesaji] = ERROR_MESSAGE() END CATCH
CATCH blogunda kullanilan fonksiyonlar ve açiklamalari su sekilde; ERROR_NUMBER : Olusan hata numasi ERROR_MESSAGE : Olusan hataya ait hata mesaji. ERROR_LINE : Hatanin hangi satirda olustugunu gösterir. ERROR_SEVERITY : Hatanin önem düzeyini gösterir. CATCH blogu önem seviyesi 11 ve üzerinde olan hatalari yakalar. 11 - 16 arasinda olan hatalar kullanici veya kod hatasidir. 17-25 arasinda olan hatalar ise yazilim ve donanimdan kaynaklanan hatalardir. ERROR_PROCEDURE : Eger hata bir stored procedure içinde olustu ise onun adini döndürür.
Hatalar
Örnek BEGIN TRY DROP TABLE OlmayanTablo; END TRY BEGIN CATCH PRINT 'Hata oluştu' PRINT ERROR_NUMBER(); PRINT ERROR_MESSAGE(); END CATCH;
SQL'de Hata Fırlatmak RAISERROR Kullanımı Bazı durumlarda SQL serverın hata fırlatmasını beklemeden kendimiz sorgunun hata fırlatıp bitmesini isteriz. Örneğin TRY CATCH ile yakalanamayan hataları kullanıcıya bildirebilmek için TRY CATCH yapısı içinde RAISERROR fonksiyonunu kullanabiliriz. Ayrıca bu fonksiyon ile kullanıcıya istemiş olduğumuz mesajı verme hakkına da sahibiz. İstediğimiz durum SQL Hatası olmayıp bizim koyduğumuz kontrol neticesinde bir mantık hatası olabilir. RAISERROR Fonksiyonu RAISERROR('Hata Mesajımız',ERROR_SEVERITY, ERROR_STATE) Seviye: 0-25 arasında bir sayı olup, mesajın kritik seviyesini gösterir. Durum: 1-127 arasında bir sayı olup, hata mesajı birden fazla yerde oluştuğunda hata oluşan yerleri ayırt etmek için kullanılır.
begin try raiserror('Hata mesajım', 11, 0) end try begin catch print('Hata oluşmuştur') end catch
BEGIN TRY PRINT 3/0; END TRY BEGIN CATCH IF ERROR_NUMBER() = 8134 BEGIN RAISERROR('Hiç bir sayı sıfıra bölünemez, hata oluştu',16,1); END; END CATCH;
Use Northwind GO CREATE TRIGGER Dur_silme ON EskiPersonel FOR DELETE AS IF (SELECT COUNT(*) FROM Deleted) > 1 BEGIN RAISERROR(‘bir kayıttan fazlasını silemezsiniz’, 16, 1) ROLLBACK TRANSACTION END DELETE FROM EskiPersonel
Hata Mesajı Eklemek Kendi uygulamalarımız için sistem mesajlarna yenilerini ekleyebilirsiniz.
Transaction Transactionlar genelde yoğun işlem yapılan ve işlemlerin tamamen bitmesinin çok önemli olduğu zamanlarda kullanılır. Eğer sorgularınız Transaction içindeyse işlemlerin hepsi başarılı olana kadar tüm işlemler başarısız sayılır. Özellikle veri kaybetmeyi göze alamayacağımız zamanlarda Transactionları kullanılır.