2011-06-16 53 views
4

我想了几天来禁用所有表的约束,插入数据并启用约束。它的工作原理,但我做了一些测试,当我插入一个不尊重外键的行时,启用约束时没有错误信息。我只能看到这个约束没有被验证。启用oracle约束的问题

这是禁用

begin  
    BEGIN 
     FOR rec IN (SELECT constraint_name, table_name FROM user_constraints WHERE constraint_type = 'R' OR constraint_type = 'P') 
     LOOP 
     BEGIN 
     EXECUTE IMMEDIATE 'alter table '||rec.table_name||' disable constraint '||rec.constraint_name; 
     EXCEPTION WHEN OTHERS THEN 
      dbms_output.put_line('ERROR: alter table '||rec.table_name||' DISABLE constraint '||rec.constraint_name||';'); 
     END;  
     END LOOP; 
     DBMS_OUTPUT.PUT_LINE('CONSTRAINTS DISABLED'); 
    END; 
    BEGIN 
    FOR rec IN (SELECT trigger_name FROM user_triggers WHERE TRIGGER_NAME NOT LIKE 'BIN$%') 
     LOOP 
      EXECUTE IMMEDIATE 'alter trigger '||rec.trigger_name||' disable'; 
     END LOOP; 
    END; 
    DBMS_OUTPUT.PUT_LINE('TRIGGERS DISABLED'); 
end;  
/

代码这是代码,以使

begin 
    BEGIN 
     FOR rec IN (SELECT constraint_name, table_name FROM user_constraints where status = 'DISABLED' and constraint_type = 'R' OR constraint_type = 'P') 
     LOOP 
     BEGIN 
      EXECUTE IMMEDIATE 'alter table '||rec.table_name||' enable constraint '||rec.constraint_name; 
      dbms_output.put_line('alter table '||rec.table_name||' enable constraint '||rec.constraint_name); 
     EXCEPTION 
      WHEN OTHERS THEN 
      dbms_output.put_line('ERROR: alter table '||rec.table_name||' enable constraint '||rec.constraint_name||' ;'); 

     END; 
     END LOOP; 
    END; 
       DBMS_OUTPUT.PUT_LINE('CONSTRAINTS ENABLED'); 
    BEGIN 
     FOR rec IN (SELECT trigger_name FROM user_triggers WHERE TRIGGER_NAME NOT LIKE 'BIN$%') 
     LOOP 
      EXECUTE IMMEDIATE 'alter trigger '||rec.trigger_name||' enable'; 
     END LOOP; 
    END; 
       DBMS_OUTPUT.PUT_LINE('TRIGGERS ENABLED'); 
END; 

我不知道如何检查所有约束在年底做了回退,如果它不没有工作。

+0

如果最后的数据必须遵守这些约束条件,为什么要禁用约束? – GolezTrol 2011-06-16 14:44:25

+0

因为我用数据加载了大量的xml文件,并且我没有把它们插入到正确的顺序中,所以需要很长时间。 – 2011-06-16 14:52:40

回答

6

首先,您的代码捕捉到当约束无法启用时引发的错误,并且抛出该错误而不是重新提升它。这几乎总是一个错误。如果你不想忽略启用约束失败的事实是,你要像

FOR rec IN (SELECT constraint_name, 
        table_name 
       FROM user_constraints 
       where status = 'DISABLED' 
       and constraint_type = 'R' 
       OR constraint_type = 'P') 
LOOP 
    BEGIN 
    l_sql_stmt := 'alter table '||rec.table_name|| 
        ' enable constraint ' || rec.constraint_name; 
    dbms_output.put_line(l_sql_stmt); 
    EXECUTE IMMEDIATE l_sql_stmt; 
    EXCEPTION 
    WHEN OTHERS THEN 
     dbms_output.put_line('ERROR: ' || l_sql_stmt); 
     raise; -- re-raise the exception 
    END; 
END LOOP; 

因为ALTER TABLE是DDL,你不能回退。如果遇到启用一个约束的错误,则无法回滚所有先前约束的启用。

根据您的上次更新,听起来您可能不想禁用和启用约束。您可能只想创建可延迟的约束。

SQL> create table foo (
    2 col1 number 
    3 ); 

Table created. 

SQL> ed 
Wrote file afiedt.buf 

    1 alter table foo 
    2 add constraint pk_foo 
    3  primary key(col1) 
    4*  deferrable 
SQL>/

Table altered. 

通常情况下,这种行为就像任何其他的主键约束

SQL> insert into foo values(1); 

1 row created. 

SQL> insert into foo values(1); 
insert into foo values(1) 
* 
ERROR at line 1: 
ORA-00001: unique constraint (SCOTT.PK_FOO) violated 


SQL> rollback; 

Rollback complete. 

但如果延迟约束,它不会被提交之前不会生效。如果在事务结束时违反约束,则事务将回滚。

SQL> alter session set constraints = deferred; 

Session altered. 

SQL> select * from foo; 

no rows selected 

SQL> insert into foo values(1); 

1 row created. 

SQL> insert into foo values(1); 

1 row created. 

SQL> insert into foo values(1); 

1 row created. 

SQL> commit; 
commit 
* 
ERROR at line 1: 
ORA-02091: transaction rolled back 
ORA-00001: unique constraint (SCOTT.PK_FOO) violated 
+0

感谢您的快速回复!所以这是不可能的,因为它是DDL? – 2011-06-16 15:07:24

+0

@ Marc-Andre - 是的,不可能回滚DDL。 – 2011-06-16 15:19:43

+0

@Justin Cave感谢您的快速回复!我从许多xml文件中插入数据,但我不知道我将拥有它们的顺序,所以也许它不会在脚本运行时尊重所有的违规行为,但最终,它应该很好,因为xml尊重数据库违规。但是这是不安全的,因为有人可以编辑这些文件。有什么我可以做的吗?谢谢 – 2011-06-16 15:24:49