SQL Server 2005 Ekleme Tetikleyici Sorununu Anlamak
SQL Server 2005 ile çalışırken, tetikleyicinizin bir hedef tabloya yalnızca bir kayıt eklediği bir durumla karşılaşabilirsiniz; oysa ana ekleme işleminiz birden fazla kayıt oluşturur. Bu, özellikle bir alt sorgu kullanarak ana tablonuza veri eklerken oldukça sinir bozucu olabilir. Bu yazıda, yaygın bir sorunu ve onun potansiyel çözümünü detaylı bir şekilde ele alacağız.
Sorunun Açıklaması
Bir tblMenuItems
adlı tablonuz olduğunu hayal edin ve buna yeni kayıtlar eklediğinizde, tblMenuItemInsertSecurity
tetikleyicinizin otomatik olarak başka bir tabloya (tblRestrictedMenuItems
) kayıt eklemesini istiyorsunuz. Tetikleyici, tek bir kayıt eklendiğinde gayet iyi çalışıyor gibi görünüyor; ancak, bir alt sorgu birden fazla kayıt getirdiğinde beklenildiği gibi davranmıyor.
İşte Ekleme İfadesi
INSERT INTO [tblMenuItems] ([ID], [MenuID], [SortOrder], [ItemReference], [MenuReference], [ConcurrencyID])
SELECT [ID], [MenuID], [SortOrder], [ItemReference], [MenuReference], [ConcurrencyID]
FROM [IVEEtblMenuItems]
Tetikleyici Kod Parçası
CREATE TRIGGER [dbo].[tblMenuItemInsertSecurity] ON [dbo].[tblMenuItems]
FOR INSERT
AS
BEGIN
DECLARE @iRoleID int
DECLARE @iMenuItemID int
SELECT @iMenuItemID = [ID] FROM Inserted
DECLARE tblUserRoles CURSOR FASTFORWARD FOR SELECT [ID] FROM tblUserRoles
OPEN tblUserRoles
FETCH NEXT FROM tblUserRoles INTO @iRoleID
WHILE (@@FetchStatus = 0)
BEGIN
INSERT INTO tblRestrictedMenuItems (
[RoleID],
[MenuItemID],
[RestrictLevel])
VALUES (
@iRoleID,
@iMenuItemID,
1)
FETCH NEXT FROM tblUserRoles INTO @iRoleID
END
CLOSE tblUserRoles
DEALLOCATE tblUserRoles
END
Tetikleyicinin Neden Başarısız Olduğunu Anlamak
Tetikleyicinizin çoklu kayıt eklememesinin temel nedeni, Inserted
sahte tablo kullanımına bağlıdır. Tetikleyici çalıştığında, Inserted
tablosu eklenen tüm satırları içerir, ancak tetikleyici mantığınız yalnızca ilk satırı yanlış bir şekilde işler.
Anlaşılması Gereken Temel Kavramlar
-
Tetikleyiciler ve Satırlar: SQL Server’da bir tetikleyici, her tetikleme işlemi (ekleme, güncelleme, silme) için bir kez tetiklenir ve birden fazla satır üzerinde aynı anda işlem yapabilir.
-
Inserted Sahte Tablosu: Bu tablo, eklenen kayıtlara erişim sağlar ve yalnızca ilki değil, tüm satırları içerir.
Çözüm: Tetikleyici Mantığını Ayarlamak
Birden fazla kayıt için eklemeleri etkili bir şekilde işlemek için tetikleyicinizi iki şekilde yeniden yapılandırabilirsiniz: bir döngüyle bir imlec kullanarak (detaylandıracağız) veya set tabanlı işlemleri kullanarak, bu daha verimlidir.
1. Bir İmlec ile Yeniden Yapılandırma
Inserted
sahte tablosu üzerinden bir imlec kullanarak döngü yapabilirsiniz, ancak bu yaklaşım büyük veri kümesiyle performans sorunlarına yol açabilir.
İşte bir imlec kullanarak tetikleyicinizin gözden geçirilmiş bir versiyonu:
CREATE TRIGGER [dbo].[tblMenuItemInsertSecurity] ON [dbo].[tblMenuItems]
FOR INSERT
AS
BEGIN
DECLARE @iRoleID int
DECLARE @iMenuItemID int
DECLARE tblUserRoles CURSOR FASTFORWARD FOR SELECT [ID] FROM tblUserRoles
OPEN tblUserRoles
FETCH NEXT FROM tblUserRoles INTO @iRoleID
-- Inserted tablosundaki her satır için döngü
DECLARE tblInserted CURSOR FOR SELECT [ID] FROM Inserted
OPEN tblInserted
FETCH NEXT FROM tblInserted INTO @iMenuItemID
WHILE @@FETCH_STATUS = 0
BEGIN
WHILE (@@FetchStatus = 0)
BEGIN
INSERT INTO tblRestrictedMenuItems (
[RoleID],
[MenuItemID],
[RestrictLevel])
VALUES (
@iRoleID,
@iMenuItemID,
1)
FETCH NEXT FROM tblUserRoles INTO @iRoleID
END
FETCH NEXT FROM tblInserted INTO @iMenuItemID
END
CLOSE tblInserted
DEALLOCATE tblInserted
CLOSE tblUserRoles
DEALLOCATE tblUserRoles
END
2. Set-Bazlı İşlemler Kullanmak (Tavsiye Edilir)
Bu yöntem daha verimlidir ve gereksiz döngüleri önler.
Mantığı doğrudan Inserted
tablosu ile birleştirecek şekilde değiştirin:
CREATE TRIGGER [dbo].[tblMenuItemInsertSecurity] ON [dbo].[tblMenuItems]
FOR INSERT
AS
BEGIN
INSERT INTO tblRestrictedMenuItems ([RoleID], [MenuItemID], [RestrictLevel])
SELECT u.[ID], i.[ID], 1
FROM tblUserRoles u
JOIN Inserted i ON <eğer gerekiyorsa bir koşul>
END
Bu kod parçası, Inserted
tablosundaki her satır için ilgili sayıda kaydın tblRestrictedMenuItems
tablosuna eklenmesini sağlar.
Sonuç
Tetikleyicilerin davranışını anlamak ve Inserted
sahte tablosunu düzgün bir şekilde kullanmak, SQL Server 2005 tetikleyicilerinizin birden fazla kayıt eklemesiyle etkin bir şekilde çalışmasını sağlar. Optimal performans için belirli bağlamınıza göre iteratif veya set-tabana dayalı yaklaşımlar arasında seçim yapın.
Yukarıda belirtildiği gibi tetikleyicinizi revize etmek için adımları izlerseniz, artık beklenen davranışı görmeli ve ana tabloda toplu eklemeler yaptığınızda hedef tablonuza birden fazla kaydın eklendiğini görmelisiniz.