1
            create or replace trigger UPDATE_HISTORY
            BEFORE INSERT OR UPDATE ON MAIN_TABLE
            FOR EACH ROW
            BEGIN

            IF UPDATING THEN

            INSERT INTO HISTORY(
                ID,
                STATUS_ID
            )
            VALUES 
            (
                :OLD.ID,
                :OLD.STATUS_ID
            );

            ELSE

            :NEW.id := id_seq.nextval; 

            INSERT INTO HISTORY(
                ID,
                STATUS_ID
            )
            VALUES 
            (
                :NEW.ID,
                :NEW.STATUS_ID
            );

            END IF;

            END;

我目前遇到一个问题,我可以在 MAIN_TABLE 中创建新记录时插入数据,但是当我来更新此表中的记录时,它会抛出错误。我正在使用一个序列来为 History 表创建一个新的 id。

我收到的错误是“违反 - 未找到父键”/“第 21 行 ORA-04088:执行触发器时出错”。

4

2 回答 2

3

这里有两种情况我认为会导致错误。

我认为您正在点击的是插入新行。您正试图在插入主表之前插入历史表。因此,违反了外键约束,因为没有父记录可供子记录参考。为避免这种情况,您可以将约束设置为延迟,因此在您提交之前不会对其进行检查;或使用 AFTER 触发器插入历史表。

另一个问题是,如果更新更改了主表中行的 ID。触发器将插入一条历史记录;那么更新本身将失败,因为存在具有旧 ID 值的子记录。这可能是所需的行为,因为您通常不希望人们无论如何修改 PK 值。

于 2015-11-06T02:26:17.730 回答
0

因此,根据您的评论ID is the PK of MAIN_TABLE and the FK of HISTORY:并根据参照完整性规则:

外键是一种在 Oracle 数据库中强制执行参照完整性的方法。外键意味着一个表中的值也必须出现在另一个表中。

被引用的表称为父表,而具有外键的表称为子表。子表中的外键一般会引用父表中的主键。

在 INSERT 上:您的触发器会将新 ID(插入到 MAIN_TABLE 中)插入到历史表中。所以在这里,FK(在 HISTORY 中是 ID)在 MAIN_TABLE 中有 PK - 工作正常。

但是,在 UPDATE:中,您的 MAIN_TABLE 中的 ID 已被新 ID 替换。但是您正试图将旧的插入历史表(已在 MAIN_TABLE 中替换)。所以这个 FK 不再出现在 MAIN_TABLE 中。这违反了您已有的参照完整性规则。

示例
您在 MAIN_TABLE 中有一行 ID=3,您将其更新为 ID=5。更新时,您的触发器正在尝试将 ID=3 插入历史记录 (:old.ID)。但是 3 在 MAIN_TABLE 中不再存在

解决方案
这完全取决于您要实现的逻辑,以及您要实现的目标。如果要存储 :old.ID,您可能需要删除此特定列的 FK 约束。或者您可能想将 :old.ID 存储在花药列中并使用 :new.ID 作为 FK

在此处阅读有关 FK的信息

于 2015-11-06T02:11:40.313 回答