2012-02-18 21 views
5

Aynı tablodaki bir alanı silmek istiyorum, ancak kaydın nasıl silindiğinden emin değil. tablo oldukça basit ve üzerinde kendi kendine referansı vardır:SQL Server 2008 - DELETE tetikleyicisi ile bir alan nasıl güncellenir

İşte
UserID FName EmailAddress EmailUserID 
1   Frank [email protected] 2 
2   Jane [email protected] NULL 
3   John [email protected] 1 
4   Brett [email protected] 2 

benim tetik: Yani

CREATE TRIGGER [dbo].[CAT_DeleteUser] 
    ON Users 
    AFTER DELETE 
AS 
BEGIN 

    SET NOCOUNT ON; 

    UPDATE Users 
    SET EmailUserID = NULL 
    WHERE EmailUserID = ID_OF_DELETED_USER <-- don't know how to get this 

END 

Ben Jane (UserID = 2) silerseniz, ben güncellemek tetiği istiyorum EmailUserID 2 ile herhangi bir kayıt. Bunu nasıl yapabilirim?

CREATE TRIGGER [dbo].[CAT_DeleteUser] 
    ON Users 
    AFTER DELETE 
AS 
BEGIN 

    SET NOCOUNT ON; 

    UPDATE Users 
    SET EmailUserID = NULL 
    WHERE EmailUserID IN (SELECT UserID FROM DELETED) 

END 
+0

Biliyorsunuz ki bu sadece kendi kendini referans alan bir yabancı anahtarınız yoksa * çalışacaksınız, değil mi? Yani, EmailUserID'de herhangi bir değeri girebileceğiniz anlamına gelir ve SQL Server, şikayet etmeyecektir. –

cevap

3

Not olduğunu eğer Tabloyu uygun bir FOREIGN KEY kısıtlaması ile ayarlayın, bir tetikleyici işi yapmadan sonra. DELETE tetikleyici operasyonları öncesi mantıksal olur, bu yüzden alacak:

Msg 547, Level 16, State 0, Line 2 
The DELETE statement conflicted with the SAME TABLE REFERENCE constraint ... 

kimsenin EMailUserID sütuna çöp şeyler böylece veri bütünlüğünü istiyoruz eğer Yani, bir INSTEAD OF tetikleyici kullanabilirsiniz şöyle:

CREATE TABLE dbo.Users 
(
    UserID INT NOT NULL PRIMARY KEY, 
    FName NVARCHAR(32), 
    EmailAddress VARCHAR(320), 
    EmailUserID INT NULL FOREIGN KEY REFERENCES dbo.Users(UserID) 
); 
GO 

CREATE TRIGGER [dbo].[CAT_DeleteUser] 
ON dbo.Users 
INSTEAD OF DELETE 
AS 
BEGIN 
    SET NOCOUNT ON; 

    -- clean up references first 
    UPDATE u SET u.EmailUserID = NULL 
     FROM dbo.Users AS u 
     INNER JOIN deleted AS d 
     ON u.EmailUserID = d.UserID; 

    -- now delete the row 
    DELETE u 
    FROM dbo.Users AS u 
    INNER JOIN deleted AS d 
    ON u.UserID = d.UserID; 
END 
GO 

Numune ardından) bu çalıştırmak tempdb yılında, yukarıdaki gibi, dbo.Users bir kopyasını oluşturmak deneyin:

INSERT dbo.Users(UserID, FName, EmailAddress, EmailUserID) VALUES 
(1,'Frank','[email protected]',2 ), 
(2,'Jane ','[email protected] ',NULL), 
(3,'John ','[email protected] ',1 ), 
(4,'Brett','[email protected]',2 ); 

SELECT * FROM dbo.Users; 
GO 

DELETE dbo.Users WHERE UserID = 2; 
GO 

SELECT * FROM dbo.Users; 
GO 

DROP TABLE dbo.Users; 
GO 
2

Üzgünüm, yanlış ilk kez ... tetik sonra bir bu durumda mümkündür sorum var

CREATE TRIGGER [dbo].[CAT_DeleteUser] ON Users 
    AFTER DELETE 
AS 
BEGIN 

    SET NOCOUNT ON; 

    UPDATE Users 
    SET EmailUserID = NULL 
    FROM Users 
    JOIN DELETED 
     ON Users.EmailUserID = Deleted.UserID 

END 
+0

Bunu kısaca açıklayabilir misiniz? Bu görünümüyle, WHERE EmailUserID IN'yi (SELECT UserID FROM DELETED) koymak istemediğiniz sürece, UserID'nin DELETE UserID olduğu kullanıcı tablosunu güncelleştirir. – Robert

+0

@Robert: Kullanıcı tablosunu güncellemek ve satır orijinal silme ifadesinden etkilenmişse, e-postadaki EmailUserID sütununu ayarlamak ister misiniz? Kullanıcı kimliğinin tablonun PK'si olduğunu varsayarsak, tetikleyici tüm satırlarda null olarak geçersiz kılar ve orijinal silme deyimi tarafından silinmesi gerekir. – Mithrandir

+0

Burada da bir düzeltme yaptım. UserID'lerin eşleştiği satırı güncelliyordunuz. @Oleg ile aynı fikirdeyim ki soruya daha yakından bakmalısın. –

7

Sen SONRA kullanmak SİL olabilir Tetik:

+0

İki düzeltme yaptım. Kimlik sütunu yok; UserID olarak düzeltildi. Ayrıca, E-posta İstemcisi'nin her iki Kullanıcıda varolması ve silinmesi nedeniyle birleştirmeyi de nitelendirdi. Bu, belirsiz sütun adından dolayı ayrıştırma başarısız olur. –

+0

@AaronBertrand Çok fazla. –

+0

@OlegDok: Gerçekten üzgünüm, yanlış anladım. – Mithrandir