在使用 YashanDB 构建数据模型过程中,部分用户在创建自关联外键表并插入数据时,遇到如下错误:


YAS-02033 foreign key constraint violated parent key not found

这类报错在 Oracle 中并不会出现,YashanDB 却插入失败。为什么会这样?本文将详细解析原因,并给出规避建议。
image.png

一、问题现象复现

建表语句:

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

二、影响与风险

image.png
三、问题原因解析

关键点在于外键校验的

YashanDB 当前对外键完整性约束的判断采用的是“逐行校验”模式:

每插入一行数据,立即检查其外键是否存在;

不会等待整个事务完成后统一判断。

而上面的插入语句是两行数据互为父子关系,同时插入,如果系统逐行判断:

插入第1行:t2=2.但此时 t1=2 还没插入,判断失败;

插入第2行:同理。

最终,报外键违反错误。

image.png
四、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 后续版本若支持事务级外键校验,则该问题可自动解决。当前尚未支持。

六、经验总结

image.png


数据库砖家
1 声望0 粉丝