字段更新时的SQL触发器,用于在另一个表中插入新记录

字段更新时的SQL触发器,用于在另一个表中插入新记录,sql,oracle,triggers,Sql,Oracle,Triggers,我试图在表中记录数据的更改。我读过很多种方法,听起来更方便,但在我的情况下,我想用触发器实现这个功能。我有两张桌子: CREATE TABLE Applications ( Application_ID INT NOT NULL, Student_ID INT NOT NULL, Job_ID INT NOT NULL, ApplicationChange_TYPE VARCHAR(64) NOT NULL, PRIMARY KEY (Application_ID),

我试图在表中记录数据的更改。我读过很多种方法,听起来更方便,但在我的情况下,我想用触发器实现这个功能。我有两张桌子:

CREATE TABLE Applications
(
  Application_ID INT NOT NULL,
  Student_ID INT NOT NULL,
  Job_ID INT NOT NULL,
  ApplicationChange_TYPE VARCHAR(64) NOT NULL,

  PRIMARY KEY (Application_ID),
  FOREIGN KEY (Student_ID) REFERENCES Students(Student_ID),
  FOREIGN KEY (Job_ID) REFERENCES Jobs(Job_ID),

  CONSTRAINT CK_TYPE CHECK (ApplicationChange_TYPE in ('Submitted', 'Withdrawn', 'Invited For Interview', 'Invited to Assessment Centre', 'Rejected', 'Accepted'))
);
以及:

我想创建一个触发器,以便在编辑/更新Applications表中记录的ApplicationChange_TYPE字段时,在ApplicationChanges表中创建一条新记录。我需要它将Application\u ID和ApplicationChange\u类型从中的applications表中编辑的记录传递到ApplicationChanges中的新记录。ApplicationChange_DATETIME字段应填充当前日期

目前,两个表的主键在创建新记录时都使用序列和触发器来自动标识编号

任何意见都将不胜感激!如果我不清楚,我会道歉

编辑:

我也已经尝试过了,但是我太不确定了,它看起来太破碎了,我认为把它包括进去没有任何意义。但这是:

CREATE OR REPLACE TRIGGER ApplicationsUpdateTrigger
AFTER UPDATE ON Applications
BEGIN
  INSERT ApplicationChanges (Application_ID, ApplicationStatus_TYPE, ApplicationChange_TYPE)
  SELECT Application_ID, ApplicationStatus_TYPE FROM Applications
    JOIN inserted ON inserted.Application_ID = Applications.Application_ID
  INSERT INTO ApplicationChanges (Application_ID, ApplicationStatus_TYPE, ApplicationChange_DATETIME)
  VALUES (NULL, Application_ID, ApplicationStatus_TYPE, GETDATE())
END;
/

正如问号所说,我将坚持使用Oracle(尽管在示例触发器中使用GETDATE()建议使用SQL Server)

我不确定要在ApplicationChanges表中存储哪个ApplicationChange\u类型的值:更改前的值(旧值)还是更改后的值(新值)

让我们讨论这两种变体,假设自动递增id列的序列和触发器可以正常工作

  • 旧值:

    CREATE OR REPLACE TRIGGER ApplicationsUpdateTrigger
    AFTER UPDATE ON Applications
    FOR EACH ROW
    BEGIN
      IF (:OLD.ApplicationChange_TYPE IS NULL AND :NEW.ApplicationChange_TYPE IS NOT NULL) -- this one is actually redundunt as long as you've got NOT NULL constraint on Application.ApplicationChange_TYPE column
         OR (:OLD.ApplicationChange_TYPE <> :NEW.ApplicationChange_TYPE)
      THEN
        INSERT INTO ApplicationChanges (Application_ID, ApplicationChange_TYPE, ApplicationChange_DATETIME)
        VALUES (:OLD.Application_ID, :OLD.ApplicationChange_TYPE, sysdate);
      END IF;
    END;
    /
    
    创建或替换触发器应用程序UpdateTrigger
    更新应用程序后
    每行
    开始
    如果(:OLD.ApplicationChange_类型为NULL,而:NEW.ApplicationChange_类型为notnull)--只要您在Application.ApplicationChange_类型列上具有notnull约束,则实际上会重新卸载此类型
    或(:OLD.ApplicationChange\u类型:NEW.ApplicationChange\u类型)
    然后
    插入到ApplicationChanges(应用程序ID、应用程序更改类型、应用程序更改日期时间)
    值(:OLD.Application\u ID,:OLD.ApplicationChange\u TYPE,sysdate);
    如果结束;
    结束;
    /
    
  • 新值:

    CREATE OR REPLACE TRIGGER ApplicationsUpdateTrigger
    AFTER UPDATE OR INSERT  ON Applications
    FOR EACH ROW
    BEGIN
      IF (:OLD.ApplicationChange_TYPE IS NULL AND :NEW.ApplicationChange_TYPE IS NOT NULL) --this check is not redundant (:OLD.ApplicationChange_TYPE will be NULL on inserts)
         OR (:OLD.ApplicationChange_TYPE <> :NEW.ApplicationChange_TYPE) 
      THEN
        INSERT INTO ApplicationChanges (Application_ID, ApplicationChange_TYPE, ApplicationChange_DATETIME)
        VALUES (:NEW.Application_ID, :NEW.ApplicationChange_TYPE, sysdate);
      END IF;
    END;
    /
    
    创建或替换触发器应用程序UpdateTrigger
    在应用程序上更新或插入后
    每行
    开始
    如果(:OLD.ApplicationChange\u类型为NULL,并且:NEW.ApplicationChange\u类型不为NULL)--此检查不是多余的(:OLD.ApplicationChange\u类型在插入时将为NULL)
    或(:OLD.ApplicationChange\u类型:NEW.ApplicationChange\u类型)
    然后
    插入到ApplicationChanges(应用程序ID、应用程序更改类型、应用程序更改日期时间)
    值(:NEW.Application\u ID,:NEW.ApplicationChange\u TYPE,sysdate);
    如果结束;
    结束;
    /
    

  • 差异是相当美观的:第二个变体同时适用于更新和插入,并使用:新记录值而不是:旧记录值。

    我删除了不兼容的数据库标记。请使用您真正使用的数据库进行标记。为什么使用“序列和触发器”而不是“序列和列默认值”?问题中没有说明提问者正在使用SQL Server/TSQL,因此我已回滚了这些标记。我们的讲师建议我们这样做。我猜是因为这个项目是基于对触发器和序列的使用/理解。我在Oracle SQL Developer工作。显然,我需要更多的影响力来编辑标签,人们已经提出了编辑建议,所以我只是批准了他们,假设他们是对的。
    CREATE OR REPLACE TRIGGER ApplicationsUpdateTrigger
    AFTER UPDATE OR INSERT  ON Applications
    FOR EACH ROW
    BEGIN
      IF (:OLD.ApplicationChange_TYPE IS NULL AND :NEW.ApplicationChange_TYPE IS NOT NULL) --this check is not redundant (:OLD.ApplicationChange_TYPE will be NULL on inserts)
         OR (:OLD.ApplicationChange_TYPE <> :NEW.ApplicationChange_TYPE) 
      THEN
        INSERT INTO ApplicationChanges (Application_ID, ApplicationChange_TYPE, ApplicationChange_DATETIME)
        VALUES (:NEW.Application_ID, :NEW.ApplicationChange_TYPE, sysdate);
      END IF;
    END;
    /