TESTDB> create table t (id number not null, val number check (val > 5)); Table created. TESTDB> insert into t values(1,7); 1 row created. TESTDB> commit; Commit complete. TESTDB> insert into t values (2,4); insert into t values (2,4) * ERROR at line 1: ORA-02290: check constraint (OPS$MYUSRID.SYS_C001214102) violated TESTDB> desc t; Name Null? Type --------------------- -------- -------- ID NOT NULL NUMBER VAL NUMBER TESTDB> create table t1 as select * from t; Table created. TESTDB> desc t1; Name Null? Type -------------------- -------- ---------- ID NOT NULL NUMBER VAL NUMBER TESTDB> insert into t1 values (1, 4); 1 row created. TESTDB> ; 1* select owner, constraint_name, constraint_type, table_name, search_condition from user_constraints TESTDB> / OWNER CONSTRAINT_NAME C TABLE_NAME SEARCH_CONDITION ------------ ------------------------------ - ---------- ------------------------------ OPS$MYUSRID SYS_C001214102 C T val > 5 OPS$MYUSRID SYS_C001214101 C T "ID" IS NOT NULL OPS$MYUSRID SYS_C001214103 C T1 "ID" IS NOT NULL
To create the constraints in the new table, I thus faced a task to extract all the DDL about constraints from the existing table. The approach I adopted after several tests was as follows.
1. First, I created a table my_constraints to have CLOB datatype for search_conditon column since we can not use LIKE operater on a LONG type column.
create table my_constraints ( owner varchar2(30) , constraint_name varchar2(30) , constraint_type varchar2(1) , table_name varchar2(30) , search_condition clob ) ; insert into my_constraints select owner, constraint_name, constraint_type, table_name, to_lob(search_condition) from dba_constraints where owner =&owner ;
2. For PK, UK and check constraints ( excluding NOT NULL), I used the following command to extract the DDL:
SELECT DBMS_METADATA.GET_DDL('CONSTRAINT', t.constraint_name , t.owner ) ddl_string from my_constraints t where table_name = upper('&table_name') and owner=upper('&owner') and constraint_type in ('P', 'U','C') and ( search_condition is null or ( search is not null and search_condition not like '%NOT NULL') ) ;
3. For FK constraints, I used the following command to extract the DDL
SELECT to_char(DBMS_METADATA.GET_DEPENDENT_DDL('REF_CONSTRAINT', table_name, owner)) DDL FROM (SELECT DISTINCT b.table_name, b.owner from dba_constraints b where b.constraint_type = 'R' AND b.owner = upper('&owner') AND b.table_name = upper('&table_name')) ;
CTAS also does not preserve DEFAULT values of columns. I used the following to obtain the 'ALTER TABLE' statement for DAFAULTS:
BEGIN FOR r IN ( select owner, table_name, column_name, data_type, data_default from dba_tab_columns where owner = upper('&owner') and table_name = upper('&table_name') and data_default is not null ) LOOP DBMS_OUTPUT.PUT_LINE ( 'ALTER TABLE ' || r.owner || '.' || r.table_name || ' modify ' ||r.column_name || ' default ' || r.data_default || ';'); END LOOP; END; /
The reason we need to use PL/SQL instead of SQL is that DATA_DEFAULT column is LONG type. We can not use '||' with LONG type column.
No comments:
Post a Comment