更新或删除时的 SQL 触发器

Jon*_*rda 1 t-sql sql-server

我必须有一个触发器来触发更新或删除操作。当更新某一列时,我的触发器工作正常。但是,当触发 DELETE 操作时,我需要不同的逻辑。我如何在一个触发器中同时拥有这两种逻辑?这是我到目前为止所拥有的:

ALTER TRIGGER [dbo].[Audit_Emp_Trigger]
   ON  [dbo].[EMPLOYEE]
   AFTER UPDATE, DELETE
AS 

BEGIN
    --Only execute the trigger if the Dno field was updated or deleted
    IF UPDATE(Dno)
    BEGIN

    --If the Audit_Emp_Record table does not exist already, we need to create it
    IF OBJECT_ID('dbo.Audit_Emp_Record') IS NULL
    BEGIN
    --Table does not exist in database, so create table
    CREATE TABLE Audit_Emp_Record
    (
    date_of_change smalldatetime,
    old_Lname varchar (50),
    new_Lname varchar (50),
    old_ssn int,
    new_ssn int,
    old_dno int,
    new_dno int
    );

    --Once table is created, insert the values of the update operation into the table
    INSERT INTO Audit_Emp_Record(date_of_change, old_Lname, new_Lname, old_ssn, new_ssn, old_dno, new_dno) SELECT GETDATE(), D.Lname, I.Lname, D.Ssn, I.Ssn, D.Dno, I.Dno FROM inserted I JOIN deleted D ON I.Ssn = D.Ssn

    END

    ELSE
    BEGIN
    --The table already exists, so simply insert the new values of the update operation into the table
    INSERT INTO Audit_Emp_Record(date_of_change, old_Lname, new_Lname, old_ssn, new_ssn, old_dno, new_dno) SELECT GETDATE(), D.Lname, I.Lname, D.Ssn, I.Ssn, D.Dno, I.Dno FROM inserted I JOIN deleted D ON I.Ssn = D.Ssn
    END

    END

END
Run Code Online (Sandbox Code Playgroud)

Sol*_*zky 5

INSERTED您可以通过查看哪些魔术/伪表并DELETED在其中包含数据来测试操作类型。我更喜欢使用类似下面的东西:

DECLARE @Operation CHAR(1);

IF (EXISTS(SELECT * FROM inserted))
BEGIN

   IF (EXISTS(SELECT * FROM deleted))
   BEGIN
      -- rows in both has to be an UPDATE
      SET @Operation = 'U';
   END;
   ELSE
   BEGIN
      -- no rows in "deleted" has to be an INSERT
      SET @Operation = 'I';
   END;

END;
ELSE
BEGIN
   -- no rows in "inserted" has to be a DELETE
   SET @Operation = 'D';
END;
Run Code Online (Sandbox Code Playgroud)

@Operation然后,您可以在 IF 语句中使用该变量来执行其中一项或另一项操作。

就像是:

IF (@Operation = 'U')
BEGIN

    --Only execute the trigger if the Dno field was updated or deleted
    IF UPDATE(Dno)
    BEGIN
       {your current code here}
    END;
END;
ELSE
BEGIN
    {what to do if the operation is a DELETE goes here}
END;
Run Code Online (Sandbox Code Playgroud)

从技术上讲,您不需要ELSE设置 的条件@Operation = 'I';,但如果您打算将此代码复制/粘贴到各种触发器中或保留为模板,那么它处理所有三个条件没有任何害处。

另外,作为旁注,您不需要语句ELSE的条件IF OBJECT_ID('dbo.Audit_Emp_Record') IS NULL,也不INSERT INTO Audit_Emp_Record需要紧接在 后面CREATE TABLE但之前的that ENDCREATE TABLE如果它不存在,则执行该测试,然后执行INSERT该测试的外部。意义:

IF UPDATE(Dno)
BEGIN
    --If the Audit_Emp_Record table does not exist already, we need to create it
    IF OBJECT_ID('dbo.Audit_Emp_Record') IS NULL
    BEGIN
       --Table does not exist in database, so create table
       CREATE TABLE Audit_Emp_Record
       ...
    END

    INSERT INTO Audit_Emp_Record(...)
END
Run Code Online (Sandbox Code Playgroud)