28 Aralık 2009 Pazartesi

Yerine Tetikleyiciler - 'Instead Of' Triggers (MS SQL)

Microsoft SQL Server'da Instead of trigger'ların bize sağladığı en önemli avantaj, güncellenemeyen view'lerin güncellenebilir yapılmasıdır. Bu yazıda da güncellenemeyen bir view'e instead of insert trigger yazarak view'e insert yapılmasını sağlayacağız.

İlk olarak tablolarımızı oluşturmamız gerekiyor. Bir önceki yazıda (Linq) kullandığımız tabloları kullanacağız. İster elle oluşturabilirsiniz isterseniz de aşağıdaki sql sorgusunu veritabanınızda çalıştırabilirsiniz. Toplam 3 adet tablomuz bulunmakta, kısaca açıklamak gerekirse, student tablomuzda öğrenci verileri tutulmaktadır.

Bir öğrencinin istediği kadar ders alabilmesi için student_course_join tablomuz bulunmaktadır ve doğal olarak dersleri kayıt ettiğimiz bir de course tablosu bulunmaktadır.



Tabloları oluşturmak için gerekli sql sorgusunu burdan indirebilirsiniz.

Bu tablolardan 'student_course_view' ismiyle bir view oluşturuyoruz.

{code type=php}
CREATE VIEW [dbo].[student_course_view]
AS
SELECT     dbo.student.name, dbo.student.last_name, dbo.student.std_number, dbo.course.crs_title
FROM         dbo.course INNER JOIN
dbo.student_course_join ON dbo.course.crs_id = dbo.student_course_join.crs_id INNER JOIN
dbo.student ON dbo.student_course_join.std_id = dbo.student.std_id

GO
{/code}

Bu kodu çalıştırdığınızda veritabanınızda view altında student_course_view çıkmalı, çıkmıyorsa refresh yapabilirsiniz. View'sağ tıklayıp 'Open View' dediğinizde normal bir tablo gibi karşınıza çıkmalı, ancak verileri girip kaydetmeye çalışırsanız size bir hata vericektir. Bunun sebebi ise, bu view'in birden fazla tablo ile oluşmasıdır. ( View or function 'student_course_view' is not updatable because the modification affects multiple base tables.)

Bunun gibi durumlarda 'INSERT' ile veri girmemiz için 'INSTEAD OF TRIGGER' kullanıyoruz. Yazacağımız trigger şunu yapıcak, ilk olarak öğrenci için yeni bir kayıt oluşturucak, eğer yazılan ders ismi yoksa yeni bir ders girdisi oluşturacak, varsa o girdiyi kullanıp join tablosuna kayıt yapıcak.


{code type=php}
CREATE TRIGGER trigger_insert ON student_course_view
INSTEAD OF INSERT
AS
BEGIN

DECLARE @student_id int
DECLARE @course_id int

IF (NOT EXISTS (SELECT student.std_id
FROM student,inserted
WHERE student.std_number = inserted.std_number))

INSERT INTO student
SELECT name, last_name, std_number
FROM inserted

SELECT @student_id = (SELECT student.std_id FROM student, inserted WHERE student.std_number = inserted.std_number)

IF (NOT EXISTS (SELECT course.crs_id
FROM course,inserted
WHERE course.crs_title = inserted.crs_title))

INSERT INTO course
SELECT crs_title
FROM inserted

SELECT @course_id = (SELECT course.crs_id FROM course, inserted WHERE course.crs_title = inserted.crs_title)

IF (NOT EXISTS (SELECT student_course_join.std_id
FROM student_course_join
WHERE student_course_join.std_id = @student_id AND student_course_join.crs_id = @course_id))
INSERT INTO student_course_join
( std_id, crs_id) VALUES
(@student_id, @course_id)
END
{/code}
Kısaca bu trigger'ın ne yaptığını anlatmak gerekirse;
1 - ilk olarak iki adet değişken tanımlıyoruz student_id ve course_id olarak.
2 - Böyle bir öğrenci kayıtlı mı diye kontrol ediyoruz (öğrenci numarasını baz alarak)
3 - Eğer yok ise yeni kayıt oluşturuyoruz.
4 - Bu öğrencinin id'sini çekiyoruz.
5 - Aynı işlemleri ders için de yapıyoruz. Olup olmadığını kontrol edip, yoksa yeni girdi oluşturuyoruz.
6 - Bu dersinde id'sini seçiyoruz.
7 - Aynı verinin tekrarlanmaması için bu ikilinin join tablomuzda olup olmadığını kontrol ediyoruz.
8 - Eğer bu ikili join tablomuzda kayıt değilse yeni girdimizi oluşturuyoruz.

Bu trigger'ı oluşturduktan sonra, ilk başta yapamadığımız veri girme işlemini artık yapıyor olmanız lazım. Herhangi bir sorunuz olursa yorum kısmına yazabilirsiniz. Umarım bu yazı instead of trigger'lar hakkında size bilgi verebilmiştir.

Hiç yorum yok:

Yorum Gönder