假设我们有两个表如下:
Parent
╔════╦════════╦═════════════════╗
║ ID ║ Name ║ Email ║
╠════╬════════╬═════════════════╣
║ 1 ║ George ║ george@test.com ║
║ 2 ║ Peter ║ peter@test.com ║
╚════╩════════╩═════════════════╝
Child
╔════════╦══════════╦═════════════╗
║ CUSTID ║ City ║ Road ║
╠════════╬══════════╬═════════════╣
║ 1 ║ London ║ Queens Road ║
║ 1 ║ Athens ║ Makedonias ║
║ 2 ║ New York ║ 24th Steet ║
╚════════╩══════════╩═════════════╝
且child.custid
对parent.id
有约束。
我想要做的是使用declare-begin-end语句向表中添加数据,但我得到的是约束错误。我使用的陈述如下:
declare
varCustId parent.id%type;
varCustName parent.name%type := 'John';
varCustEmail parent.email%type := 'john@test.com';
begin
select max(id)+1 int varCustId from parent;
insert into parent(id,name,email) values(varCustId,varCustName,varCustEmail);
-- I tried adding a 'commit;' here but it didn't make any difference
insert into child(custid,city,road) values(varCustId, 'Thessaloniki', 'Mpotsari');
end;
我得到的消息是integrity constraint (...) violated - parent key not found
。
这样的事情是否可能,而不必禁用/删除约束并再次启用/创建它?
当然,这是我使用的表和语句的非常简化版本。
答案 0 :(得分:1)
首先,使用SELECT max(id)+1的想法在多交易环境中不起作用。你应该使用序列代替。此外,首先将数据放入父表和下一个子表中的情况绝对正确 - 如果我们谈论外键约束。 你不应该遇到问题:
SQL> create table parent (id int primary key
2 , name varchar2(20)
3 , email varchar2(40)
4 )
5 /
SQL> create table child (custid int references parent(id)
2 ,city varchar2(40)
3 ,road varchar2(40)
4 )
5 /
SQL> create sequence seq_test
2 /
SQL> declare
2 varCustId parent.id%type;
3 varCustName parent.name%type := 'John';
4 varCustEmail parent.email%type := 'john@test.com';
5 begin
6 insert into parent(id,name,email) values(seq_test.nextval,varCustName,varCustEmail)
7 returning id into varCustId;
8 insert into child(custid,city,road) values(varCustId, 'Thessaloniki', 'Mpotsari');
9 end;
10 /
SQL> select * from parent;
ID NAME EMAIL
---------- -------------------- ----------------------------------------
1 John john@test.com
SQL> select * from child
2 /
CUSTID CITY
---------- ----------------------------------------
ROAD
----------------------------------------
1 Thessaloniki
Mpotsari
如果您尝试首先插入子表,则可能会出现此问题。然后其中一个解决方案是可延迟约束(如果您不能保证某些插入顺序):
SQL> declare
2 varCustId parent.id%type;
3 varCustName parent.name%type := 'John';
4 varCustEmail parent.email%type := 'john@test.com';
5 begin
6 insert into child(custid,city,road) values(seq_test.nextval, 'Thessaloniki', 'Mpotsari')
7 returning custid into varCustId;
8 insert into parent(id,name,email) values(varCustId,varCustName,varCustEmail);
9 end;
10 /
declare
...
ORA-02291: integrity constraint constraint (ODH.SYS_C00308311) - parent key not found
..
SQL> alter table child drop constraint sys_c00308311;
SQL> truncate table child;
SQL> truncate table parent;
SQL> alter table child add constraint child_fk foreign key (custid)
2 references parent(id) deferrable initially deferred;
Таблица изменена.
SQL> declare
2 varCustId parent.id%type;
3 varCustName parent.name%type := 'John';
4 varCustEmail parent.email%type := 'john@test.com';
5 begin
6 insert into child(custid,city,road) values(seq_test.nextval, 'Thessaloniki', 'Mpotsari')
7 returning custid into varCustId;
8 insert into parent(id,name,email) values(varCustId,varCustName,varCustEmail);
9 end;
10 /
SQL> commit;
SQL> select * from parent;
ID NAME EMAIL
---------- -------------------- ----------------------------------------
3 John john@test.com
SQL> select * from child;
CUSTID CITY
---------- ----------------------------------------
ROAD
----------------------------------------
3 Thessaloniki
Mpotsari
答案 1 :(得分:0)
SELECT a.table_name, a.column_name, a.constraint_name, c.owner,
c.r_owner, c_pk.table_name r_table_name, c_pk.constraint_name r_pk
FROM all_cons_columns a
JOIN all_constraints c ON a.owner = c.owner
AND a.constraint_name = c.constraint_name
JOIN all_constraints c_pk ON c.r_owner = c_pk.owner
AND c.r_constraint_name = c_pk.constraint_name
WHERE c.constraint_type = 'R'
AND a.table_name = 'CHILDTABLE';
使用上述查询在您的表格中查找参照约束(已引用列名称)!