【问题标题】:SQL Trigger on field update to insert new record in another tableSQL 触发字段更新以在另一个表中插入新记录
【发布时间】:2016-11-05 17:21:40
【问题描述】:

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

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'))
);

还有:

CREATE TABLE ApplicationChanges
(
  ApplicationChange_ID INT NOT NULL,
  Application_ID INT NOT NULL,
  ApplicationChange_TYPE VARCHAR(64),
  ApplicationChange_DATETIME DATE NOT NULL,

  PRIMARY KEY (ApplicationChange_ID),
  FOREIGN KEY (Application_ID) REFERENCES Applications(Application_ID),

  CONSTRAINT CK_APPTYPE CHECK (ApplicationChange_TYPE in ('Submitted', 'Withdrawn', 'Invited For Interview', 'Invited to Assessment Centre', 'Rejected', 'Accepted'))
);

我想创建一个触发器,以便在编辑/更新 Applications 表中记录的 ApplicationChange_TYPE 字段时,在 ApplicationChanges 表中创建一条新记录。我需要它将 Application_ID 和 ApplicationChange_TYPE 从应用程序表中已编辑的记录转移到 ApplicationChanges 中的新记录中。 ApplicationChange_DATETIME 字段应填充当前日期。

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

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

编辑:

我也已经对此进行了尝试,但我对此非常不确定,而且它似乎很破碎,以至于我认为包含它没有任何意义。但这里是:

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;
/

【问题讨论】:

  • 我删除了不兼容的数据库标签。请标记您真正使用的数据库。
  • 为什么使用“序列和触发器”而不是“序列和列默认值”?
  • 问题中没有任何内容表明提问者正在使用 SQL Server/TSQL,所以我已经回滚了这些标签。
  • 我们的讲师建议我们这样做。我猜是因为该项目基于表示触发器和序列的使用/理解。
  • 我在 Oracle SQL Developer 工作。显然我需要更大的影响力来编辑标签,人们提出了编辑建议,所以我只是批准了他们,假设他们是对的。

标签: sql oracle triggers


【解决方案1】:

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

我不确定您要在 ApplicationChanges 表中存储哪个 ApplicationChange_TYPE 值:更改前(旧)还是更改后(新)?

让我们涵盖这两种变体,假设自动递增 id 列的序列和触发器工作正常。

  1. 旧值:

    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;
    /
    
  2. 新价值:

    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;
    /
    

差异非常美观:第二个变体适用于 UPDATE 和 INSERT,并使用 :NEW 记录值而不是 :OLD 记录值。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-12-06
    • 1970-01-01
    • 1970-01-01
    • 2023-03-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多