declare-begin-end语句中的Oracle多个事务

时间:2014-02-07 13:53:01

标签: sql oracle oracle-sqldeveloper

假设我们有两个表如下:

             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.custidparent.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

这样的事情是否可能,而不必禁用/删除约束并再次启用/创建它?

当然,这是我使用的表和语句的非常简化版本。

2 个答案:

答案 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';

使用上述查询在您的表格中查找参照约束(已引用列名称)!