Oracle 11g能否先插子表记录再插父表?需延迟FK约束检查的实现脚本
在Oracle 11g中能否先插入子表记录再插入父表记录?
当然可以实现!不过默认情况下Oracle的外键约束是立即检查的,直接先插子表会触发ORA-02291: 违反完整约束条件 - 未找到父项关键字的错误。你需要把外键约束配置为延迟检查,让数据库等到事务提交时再验证外键关系。下面我一步步给你演示怎么操作:
第一步:创建或修改带延迟检查的外键约束
首先,你的customers和orders表需要建立外键关联,并且这个外键要设置为可延迟检查的。分两种情况处理:
情况1:还没创建表,直接定义带延迟约束的表
-- 创建父表customers,cust_code作为主键 CREATE TABLE customers ( cust_code VARCHAR2(3) PRIMARY KEY, name VARCHAR2(50), region VARCHAR2(5) ) TABLESPACE mine; -- 创建子表orders,同时定义可延迟的外键约束 CREATE TABLE orders ( ord_id NUMBER(3) PRIMARY KEY, ord_date DATE, cust_code VARCHAR2(3), date_of_dely DATE, CONSTRAINT fk_orders_customers FOREIGN KEY (cust_code) REFERENCES customers(cust_code) -- DEFERRABLE表示约束可以延迟检查,INITIALLY DEFERRED表示默认就延迟 DEFERRABLE INITIALLY DEFERRED ) TABLESPACE mine;
情况2:已经创建了表,添加延迟外键约束
如果你的表已经存在,只是没加外键,可以用ALTER TABLE语句添加延迟约束:
ALTER TABLE orders ADD CONSTRAINT fk_orders_customers FOREIGN KEY (cust_code) REFERENCES customers(cust_code) DEFERRABLE INITIALLY DEFERRED;
第二步:编写DML事务脚本,先插子表再插父表
现在就可以在一个事务里先插入子表记录,再插入对应的父表记录,最后提交事务时数据库才会检查外键约束:
示例1:使用默认延迟的约束(INITIALLY DEFERRED)
BEGIN -- 先插入子表orders的记录,此时父表还没有对应的cust_code INSERT INTO orders (ord_id, ord_date, cust_code, date_of_dely) VALUES (101, SYSDATE, 'C01', SYSDATE + 7); -- 插入对应的父表customers记录 INSERT INTO customers (cust_code, name, region) VALUES ('C01', 'Alice Smith', 'NA'); -- 提交事务,此时Oracle会检查外键约束,验证子表的cust_code在父表中存在 COMMIT; END; /
示例2:手动设置延迟约束(如果约束只定义了DEFERRABLE,没有INITIALLY DEFERRED)
如果你的外键约束只设置了DEFERRABLE,默认还是立即检查,这时候需要在事务里手动开启延迟检查:
BEGIN -- 手动指定该外键约束延迟检查 SET CONSTRAINT fk_orders_customers DEFERRED; -- 先插子表 INSERT INTO orders (ord_id, ord_date, cust_code, date_of_dely) VALUES (102, SYSDATE, 'C02', SYSDATE + 7); -- 再插父表 INSERT INTO customers (cust_code, name, region) VALUES ('C02', 'Bob Johnson', 'EU'); COMMIT; END; /
注意事项
- 延迟检查只是把约束验证的时机从插入/更新时推迟到事务提交时,如果提交时父表仍然没有对应的记录,还是会触发外键约束错误。
- 只有
DEFERRABLE类型的约束才能设置延迟,默认的外键约束是NOT DEFERRABLE,无法修改为延迟检查,所以必须在创建或修改约束时明确指定DEFERRABLE。
内容的提问来源于stack exchange,提问作者user9164701
相关产品推荐
相关产品推荐

