1 Mayıs 2012 Salı

MS SQL 'de DDL Triggers

Merhaba arkadaşlar.
Şimdiye kadar gördüğümüz "DML Triggers" 'larda bir tablo üzerindeki manipülasyonları inceledik. Bir tabloya bağımlı çalışıyorlardır. Şimdi göreceğimiz "triggers" arkadaşlar ya bir veritabanı üzerindeki (create, alter, drop) yada tüm sunucudaki (all server) manipülasyonları gözlemleyerek tetiklenecek "triggers" nesneleridir. İşte bu nesnelere de "DDL Triggers" diyoruz. Örneğin veri tabanı nesneleri üzerindeki işlem yani "create, alter, drop" komutları ile manipüle edilen nesneler için "trigger" lar oluşturacağız. Bu veri tabanı nesnelerim "view, stored procedure, function, table vs.." olabilir. "DDL Triggers" nesnelerinde "After-Instead Of" gibi bir ayrım yoktur. Sadece tanımlamalarında "after" trigger söz konusudur. Fakar eğer "Instead Of  Triggers" gibi kullanmak için, tetiklenme olayının yerine bir olay gerçekleştirmek istiyorsam, trigger nesnemin gövdesi "rollback" anahtar sözcüğünü yazarak işlemin geri alınmasını sağlarım.
  • Bir veritabanı üzerinde çalışan "Trigger" nesneleri
"Trigger" nesnemiz "tirgger" 'ımızı hangi veri tabanı üzerinde oluşturmuşsak sadece o veri tabanı üzerinde çalışacaktır. Kolay bir örnekle başlayalım. Örneğin "Nortwind" veri tabanında herhangi bir "view" nesnesinin silinmesi ile tetiklenen bir "trigger" yazalım. Bir "view" silindikten sonra sadece ekrana bir yazı yazsın. Bunun için "AFTER Drop_View" kullanmalıyım.


USE Northwind

CREATE TRIGGER ViewOlusturuldu
ON DATABASE
AFTER Drop_View
AS
      PRINT 'View silmede ustasin'

"Trigger" nesnemi oluşturdum. Şimdi çalışıyor mu diye bakalım. Bir veri tabanımızdan bir "view" silelim.
DROP VIEW dbo.[Summary of Sales by Year]
"View" nesnemiz başarılı bir şekilde silindi ve görünmesini istediğimiz mesajımızı aldık. Mesaj versin fakat silmesin isteseydim "trigger" nesnemi tanımlarken sonuna "rollback" sözcüğünü eklemeliydim. Böylece yapılan işlemi geri alacaktı. Şimdi başka bir örnekte de "rollback" kullanalım. Örneğin "Nortwind" veri tabanında bir tabloda herhangi bir değişiklik işlemi yapılamasın. 

USE Northwind

CREATE TRIGGER TabloDuzenlemeEngeli
ON DATABASE
FOR Alter_Table
AS
      RAISERROR('Tablo düzenleme engeli',16,1)
      ROLLBACK
NOT: "On Database" diyerek oluşturduğumuz "DDL Trigger" nesneleri hangi veri tabanında oluşturulmuşsa, "Object Explorer" penceresinde o veri tabanı altında "Programmability", "Database Triggers" sekmesi altında yerini alır.

"Trigger" nesnemi "hata mesajımla birlikte" oluşturdum. Hata mesajına verdiğim parametrelerin anlamına, kursörunuzu "Raiserror" komtunun üstüne getirdiğinizde "shift+F1" yaparak bakabilirsiniz. 2. parametresi hatanın önem derecesidir, 10 'dan büyükse "Catch" bloğuna düşer. 20 'den büyükse(25 ' kadar) "fatal error" olur. 3. parametresi ise hatanın durumudur. Yapılan işlemi de "rollback" ile geri aldım. Şimdi çalışıyor mu diye bakalım. "Shippers" tablosuna "Hede" adında bir kolon eklemeye çalışalım. 
ALTER TABLE Shippers ADD Hede NVARCHAR(24) NULL

Hata mesajından da anlaşılacağı üzere kolonumu tabloma eklemeye izin vermedi, ekleyemedim, "transaction" sonladı, işlem iptal oldu. İşlemimiz "TabloDuzenlemeEngeli" adındaki "procedure" nesnesine takıldı. "Trighers" nesneleri otomatik çalışan "Stored Procedure" 'lerdir demiştik. Görüldüğü üzere tabirimiz doğrulandı.

Bu örnek de "DDL Triggers" 'lardaki "Instead Of" triggerı gibi tetiklenen işlem yerine, başka bir işlem yapılmasına bir örnekti arkadaşlar. Daha sonra "trigger" nesnemi "disable" ediyorum.

DISABLE TRIGGER TabloDuzenlemeEngeli ON DATABASE
  • Tüm Server üzerinde çalışan "Trigger" nesneleri
Bu "trigger" nesnelerimi tanımlarken hangi ver tabanı üzerinde tanımladığımızın bir önemi yok arkadaşlar. Çünkü "All Server" yani tüm sunucu üzerinde çalışacaktır. Örneğin sunucumda hiç bir şekilde veri tabanı oluşturulamasın istiyorum.
CREATE TRIGGER VeriTabaniOlusturmaEngeli
ON ALL SERVER
FOR create_database
AS
      RAISERROR('Yetkilen de gel !!',16,1)
      ROLLBACK
Görüldüğü üzere arkadaşlar "All Server" deyimi ile oluşturulan "Trigger" nesneleri, "Object Explorer" penceresinde, hiç bir veri tabanı altında değil de direk sunucuda "Server Object", "Triggers" sekmesinin altında yerini alıyor. 
 "Trigger" nesnemi "hata mesajımla birlikte" oluşturdum. Bir veri tabanı oluşturmaya çalışalım bakalım oluşturabilecek miyiz.
CREATE DATABASE DenemeDB

Görüldüğü üzere işlemimiz "VeriTabaniOlusturmaEngeli" adındaki "procedure" nesnesine takıldı. Unutmadan "trigger" 'ımı "disable" ediyorum.
disable trigger VeriTabaniOlusturmaEngeli on all server

Başka bir örnekte ise işlem yapıldıktan sonra bir mesaj verelim. Sunucuda herhangi bir veri tabanından bir tablo silindiğinde mesaj versin. 
CREATE TRIGGER TabloSilme
ON ALL SERVER
AFTER DROP_TABLE
AS
      PRINT 'Tablo Silmene Hastayim'
"Trigger" nesnemizin çalışmasını kontrol etmek için herhangi ver tabanından, herhangi bir tabloyu silelim.
DROP TABLE Kitapci.dbo.Hede

Umarım yardımcı olabilmişimdir. Bir başka yazıda görüşmek dileğiyle, hoşçakalın...

2 yorum: