2012-02-18 5 views
5

Quiero actualizar un campo en la misma tabla desde la que se está eliminando el registro, pero no estoy muy seguro de cómo hacerlo. La mesa es bastante simple y tiene una autorreferencia en él:SQL Server 2008 - Cómo actualizar un campo con el activador DELETE

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

Aquí es mi gatillo:

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 

Así que si elimino Jane (UserID = 2), me gustaría que el gatillo para actualizar cualquier registro con EmailUserID de 2. ¿Cómo puedo lograr esto?

+0

Sabes que esto solo funcionará si * no * tienes una clave foránea autorreferencial, ¿verdad? Lo que significa que puede rellenar cualquier valor en EmailUserID y SQL Server no se va a quejar. –

Respuesta

3

Tenga en cuenta que si configure la tabla con una restricción apropiada de FOREIGN KEY, un disparador posterior no hará el trabajo. El DELETE sucede lógicamente antes de que las operaciones en el gatillo, por lo que obtendrá:

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

Así que si usted desea que la integridad de datos para que nadie pueda meter la basura en la columna de la EMailUserID, puede utilizar un disparador INSTEAD OF de la siguiente manera:

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 

Muestra intentar crear una copia de dbo.Users, como anteriormente, en tempdb, a continuación, ejecutar este):

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

Lo sentimos, consiguió la pregunta equivocada la primera vez ... Un después del disparo es posible en este caso:

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

¿Puede explicar esto brevemente? Por lo que parece, esto actualizaría la tabla de usuarios donde el ID de usuario es el ID de usuario DELETE, a menos que desee colocar WHERE EmailUserID IN (SELECCIONAR ID de usuario FROM DELETED). – Robert

+0

@Robert: ¿Desea actualizar la tabla de usuarios y establecer la columna EmailUserID en nulo si la fila se vio afectada por la instrucción de eliminación original, ¿verdad? Suponiendo que el ID de usuario es el PK de la tabla, el desencadenante establece que EmailUserID anule en todas las filas, que estaban destinadas a ser eliminadas por la declaración de eliminación original. – Mithrandir

+0

También hice una corrección aquí. Estabas actualizando la fila donde coincidían los ID de usuario. Estoy de acuerdo con @Oleg, es necesario que mires más de cerca la pregunta. –

7

Usted puede usar después de BORRAR disparador:

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

He hecho dos correcciones. No hay una columna de ID; lo corrigió como ID de usuario. También calificó la unión porque EmailUserID existe en ambos usuarios y se eliminó; esto debería fallar en el análisis debido a un nombre de columna ambiguo. –

+0

@AaronBertrand Thanx mucho. –

+0

@OlegDok: Realmente lo siento, me equivoqué bastante. – Mithrandir

Cuestiones relacionadas