更新时可以插入,但插入时不能
Can INSERT when UPDATING but not when INSERTING
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 中创建新记录时插入数据,但是当我在此 table 中更新记录时,它会返回并出错。我正在使用一个序列为历史 table.
创建一个新的 ID
我收到的错误是 "violated - parent key not found" /“第 21 行 ORA-04088:触发器执行期间出错”。
因此根据您的评论 ID is the PK of MAIN_TABLE and the FK of HISTORY
:
并根据引用完整性规则:
A foreign key is a way to enforce referential integrity within your Oracle database. A foreign key means that values in one table must also appear in another table.
The referenced table is called the parent table while the table with the foreign key is called the child table. The foreign key in the child table will generally reference a primary key in the parent table.
在插入时: 您的触发器会将新 ID(已插入 MAIN_TABLE)插入历史记录 table。所以在这里,FK(历史中的 ID)在 MAIN_TABLE 中有 PK - 工作正常。
更新时:,但是,您的 MAIN_TABLE 中的 ID 已被新 ID 替换。但是您正在尝试将旧的插入到历史记录 table 中(它已在 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 here
这里有两种情况我觉得会报错
我认为您遇到的问题是插入新行。您正在尝试插入到历史 table 之前 插入到主 table 实际发生。因此,违反了外键约束,因为没有父记录可供子项引用。为避免这种情况,您可以将约束设置为延迟,这样在您提交之前不会对其进行检查;或使用 AFTER 触发器插入历史 table.
另一个问题是更新更改了主 table 中行的 ID。触发器会插入一条历史记录;那么更新本身就会失败,因为存在具有旧 ID 值的子记录。这可能是期望的行为,因为您通常不希望人们无论如何都修改 PK 值。
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 中创建新记录时插入数据,但是当我在此 table 中更新记录时,它会返回并出错。我正在使用一个序列为历史 table.
创建一个新的 ID我收到的错误是 "violated - parent key not found" /“第 21 行 ORA-04088:触发器执行期间出错”。
因此根据您的评论 ID is the PK of MAIN_TABLE and the FK of HISTORY
:
并根据引用完整性规则:
A foreign key is a way to enforce referential integrity within your Oracle database. A foreign key means that values in one table must also appear in another table.
The referenced table is called the parent table while the table with the foreign key is called the child table. The foreign key in the child table will generally reference a primary key in the parent table.
在插入时: 您的触发器会将新 ID(已插入 MAIN_TABLE)插入历史记录 table。所以在这里,FK(历史中的 ID)在 MAIN_TABLE 中有 PK - 工作正常。
更新时:,但是,您的 MAIN_TABLE 中的 ID 已被新 ID 替换。但是您正在尝试将旧的插入到历史记录 table 中(它已在 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 here
这里有两种情况我觉得会报错
我认为您遇到的问题是插入新行。您正在尝试插入到历史 table 之前 插入到主 table 实际发生。因此,违反了外键约束,因为没有父记录可供子项引用。为避免这种情况,您可以将约束设置为延迟,这样在您提交之前不会对其进行检查;或使用 AFTER 触发器插入历史 table.
另一个问题是更新更改了主 table 中行的 ID。触发器会插入一条历史记录;那么更新本身就会失败,因为存在具有旧 ID 值的子记录。这可能是期望的行为,因为您通常不希望人们无论如何都修改 PK 值。