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:执行触发器时出错"。
答案 0 :(得分:3)
我认为这有两种情况会导致错误。
我认为你要击中的是插入一个新行。您试图在之前插入到历史表中实际发生插入主表。因此,违反了外键约束,因为没有父记录供子引用。为避免这种情况,您可以将约束设置为延迟,因此在您提交之前不会检查它;或使用AFTER触发器插入历史表。
另一个问题是,如果更新更改了主表中行的ID。触发器将插入历史记录;然后更新本身将失败,因为子记录存在旧ID值。这可能是理想的行为,因为您通常不希望人们修改PK值。
答案 1 :(得分:0)
所以根据您的评论ID is the PK of MAIN_TABLE and the FK of HISTORY
:
并根据参考完整性规则:
外键是一种在Oracle数据库中强制引用完整性的方法。外键意味着一个表中的值也必须出现在另一个表中。
引用的表称为父表,而具有外键的表称为子表。子表中的外键通常会引用父表中的主键。
On INSERT:您的触发器会将新ID(插入MAIN_TABLE中)插入History表。所以在这里,FK(在HISTORY中是ID)在MAIN_TABLE中具有PK - 工作正常。
在更新:,但是,MAIN_TABLE中的ID已被新ID替换。但是你试图将旧的一个插入到历史表中(已经在MAIN_TABLE中替换)。所以这个FK不再出现在MAIN_TABLE中了。这违反了您已实施的参照完整性规则。
示例强>
您在MAIN_TABLE中有一行ID = 3,并将其更新为ID = 5。在更新时,您的触发器尝试将ID = 3插入到History(:old.ID)中。但是在MAIN_TABLE中不再存在3
<强>解强>
这一切都取决于你想要实现的逻辑,以及你想要实现的目标。如果要存储:old.ID,则可能需要删除此特定列上的FK约束。或者您可能希望在anther列中存储:old.ID并使用:new.ID作为FK
了解FK here