可以在更新时插入但在插入时不插入

时间:2015-11-06 01:56:20

标签: sql oracle plsql database-trigger

            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:执行触发器时出错"。

2 个答案:

答案 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