在使用 YashanDB 构建数据模型过程中,部分用户在创建自关联外键表并插入数据时,遇到如下错误:
YAS-02033 foreign key constraint violated parent key not found
这类报错在 Oracle 中并不会出现,YashanDB 却插入失败。为什么会这样?本文将详细解析原因,并给出规避建议。
一、问题现象复现
建表语句:
drop table self_f_key;
create table self_f_key (
t1 number primary key not null,
t2 number
);
create index i_s_1 on self_f_key(t2);
alter table self_f_key
add constraint c_0001 foreign key(t2) references self_f_key(t1);
插入语句:
insert into self_f_key
select 1. 2 from dual
union all
select 2. 1 from dual;
该插入语句中,两行数据是互相引用的,理论上在同一事务中应满足外键约束。
但在 YashanDB 中执行会报错:
YAS-02033 foreign key constraint violated parent key not found
二、影响与风险
三、问题原因解析
关键点在于外键校验的
YashanDB 当前对外键完整性约束的判断采用的是“逐行校验”模式:
每插入一行数据,立即检查其外键是否存在;
不会等待整个事务完成后统一判断。
而上面的插入语句是两行数据互为父子关系,同时插入,如果系统逐行判断:
插入第1行:t2=2.但此时 t1=2 还没插入,判断失败;
插入第2行:同理。
最终,报外键违反错误。
四、Oracle 的行为
Oracle 对同样的插入语句不会报错,原因是:
Oracle 支持事务级外键判断;
会等待整个 INSERT ALL 完成后,再判断外键约束是否成立;
这样在事务内部引用自己的数据是被允许的。
五、解决办法与规避建议
1、暂时关闭外键约束(推荐)
在插入前关闭约束,插入后重新启用:
alter table self_f_key disable constraint c_0001; -- 执行插入语句 alter table self_f_key enable validate constraint c_0001;
2、拆分插入语句
将数据分批插入,确保父行先插入:
insert into self_f_key values (1. null); insert into self_f_key values (2. 1); update self_f_key set t2 = 2 where t1 = 1;
3、等待后续版本优化
YashanDB 后续版本若支持事务级外键校验,则该问题可自动解决。当前尚未支持。
六、经验总结
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。