create table as 的陷阱

   對與一個DBA來說,create table ..as ..語句的使用應該是最平常不過的了,使用這個方法創建表的速度是速度是最快的,

 尤其是當我們想複製一張大表時,由於create as 是DDL語句,不需要寫undo數據,這種創建方法要比insert要快很多倍,可是這種方法有一個很大的弊端,就是對原表的任何約束都是無效的。
 我們可以通過以下的例子來看:
----查看emp存在的索引和約束
orcl@ SCOTT> select INDEX_NAME,INDEX_TYPE,table_OWNER,TABLE_NAME from user_indexes where table_name='EMP';
 
INDEX_NAME      INDEX_TYPE      TABLE_OWNER     TABLE_NAME
--------------- --------------- --------------- ---------------
PK_EMP          NORMAL          SCOTT           EMP
IND_EMP         NORMAL          SCOTT           EMP
IND_EMP1        NORMAL          SCOTT           EMP
 
Elapsed: 00:00:00.01
orcl@ SCOTT> 
orcl@ SCOTT> select owner,constraint_name,table_name from user_constraints;
 
OWNER      CONSTRAINT_NAME      TABLE_NAME
---------- -------------------- ---------------
SCOTT      FK_DEPTNO            EMP
SCOTT      PK_DEPT              DEPT
SCOTT      PK_EMP               EMP
 
Elapsed: 00:00:00.18
----採用create table as 的方式 創建新表
orcl@ SCOTT> create table emp5 as select * from emp;
 
Table created.
 
Elapsed: 00:00:00.16
 
----查看新表是否存在約束
orcl@ SCOTT> select INDEX_NAME,INDEX_TYPE,table_OWNER,TABLE_NAME from user_indexes where table_name='EMP5';
 
no rows selected
 
Elapsed: 00:00:00.03
orcl@ SCOTT> select * from user_constraints where table_name='EMP5';
 
no rows selected
 
Elapsed: 00:00:00.02
orcl@ SCOTT> 
----事實證明,create table as 的方式創建新表,不會添加原表的約束
 
----如果原表中有default值的話,測試新表是否可以繼承
 
orcl@ SCOTT> 
orcl@ SCOTT> create table e1(id number default 1,name varchar2(10));
 
Table created.
 
Elapsed: 00:00:00.02
orcl@ SCOTT> insert into e1(name) values('chen');
 
1 row created.
 
Elapsed: 00:00:00.00
orcl@ SCOTT> insert into e1(name) values('cheng');
 
1 row created.
 
Elapsed: 00:00:00.01
 
Elapsed: 00:00:00.00
orcl@ SCOTT> insert into e1(name) values('chao');
 
1 row created.
 
Elapsed: 00:00:00.00
orcl@ SCOTT> insert into e1(name) values('hua');
 
1 row created.
 
Elapsed: 00:00:00.00
orcl@ SCOTT> 
orcl@ SCOTT> 
orcl@ SCOTT> commit;
 
Commit complete.
 
Elapsed: 00:00:00.00
orcl@ SCOTT> 
orcl@ SCOTT> 
orcl@ SCOTT> select * from e1;
 
        ID NAME
---------- --------------------
         1 chen
         1 cheng
         1 chao
         1 hua
 
Elapsed: 00:00:00.00
orcl@ SCOTT> 
----創建新表
orcl@ SCOTT> create table e2 as select * from e1;
 
Table created.
 
Elapsed: 00:00:00.04
orcl@ SCOTT> 
orcl@ SCOTT> 
orcl@ SCOTT> select * from e2;
 
        ID NAME
---------- ---------------
         1 chen
         1 cheng
         1 chao
         1 hua
 
Elapsed: 00:00:00.01
orcl@ SCOTT> 
orcl@ SCOTT> 
orcl@ SCOTT> insert into e2(name) values('haha');
 
1 row created.
 
Elapsed: 00:00:00.00
orcl@ SCOTT> select * from e2;
 
        ID NAME
---------- -------------
         1 chen
         1 cheng
         1 chao
         1 hua
           haha
 
Elapsed: 00:00:00.00
----create as 的新表沒有把之前的default 值複製過來
 
----通過以上的實驗,我們基本可以判定,create as 語句除了可以複製原表數據和表結構之外,其他的什麼都不能做,我們通過10053事件跟蹤一下sql語句的執行過程
通過後臺跟蹤進程查看create as 在後臺是如何執行的
orcl@ SYS> alter session set events '10053 trace name  context forever,level 1';                                     
 
Session altered.
 
Elapsed: 00:00:00.00
orcl@ SYS> 
orcl@ SYS> 
orcl@ SYS> create table scott.emp05 as select * from  scott.emp;
 
Table created.
 
Elapsed: 00:00:00.10
orcl@ SYS> 
orcl@ SYS> alter session set events '10053 trace name context off';
 
Session altered.
 
Elapsed: 00:00:00.01
orcl@ SYS> oradebug setmypid
Statement processed.
orcl@ SYS> 
orcl@ SYS> 
orcl@ SYS> oradebug tracefile_name
/home/oracle/admin/orcl/udump/orcl_ora_3050.trc
 
-----查看trace日誌
******* UNPARSED QUERY IS *******
SELECT "EMP"."EMPNO" "EMPNO","EMP"."ENAME" "ENAME","EMP"."JOB" "JOB","EMP"."MGR" "MGR","EMP"."HIREDATE" "HIREDATE","EMP"."SAL" "SAL","EMP"."COMM" "COMM","EMP"."DEPTNO" "DEPTNO" FROM "SCOTT"."EMP" "EMP"
kkoqbc-end
          : call(in-use=27028, alloc=30240), compile(in-use=31596, alloc=32640)
apadrv-end: call(in-use=27028, alloc=30240), compile(in-use=32116, alloc=32640)
 
sql_id=9f4wggut51mx0.
Current SQL statement for this session:
create table scott.emp05 as select * from  scott.emp
 
============
Plan Table
============
------------------------------------------+-----------------------------------+
| Id  | Operation               | Name    | Rows  | Bytes | Cost  | Time      |
------------------------------------------+-----------------------------------+
| 0   | CREATE TABLE STATEMENT  |         |       |       |     4 |           |
| 1   |  LOAD AS SELECT         |         |       |       |       |           |
| 2   |   TABLE ACCESS FULL     | EMP     |    14 |   518 |     3 |  00:00:01 |
------------------------------------------+-----------------------------------+
Predicate Information:
----------------------
 
Content of other_xml column
===========================
  db_version     : 10.2.0.1
  parse_schema   : SYS
  plan_hash      : 2748781111
  Outline Data:
  /*+
    BEGIN_OUTLINE_DATA
      IGNORE_OPTIM_EMBEDDED_HINTS
      OPTIMIZER_FEATURES_ENABLE('10.2.0.1')
      ALL_ROWS
      OUTLINE_LEAF(@"SEL$1")
      FULL(@"SEL$1" "EMP"@"SEL$1")
    END_OUTLINE_DATA
  */
 
-----從上面的診斷日誌可以看出,create as 只是把原表以select的方式查出來,然後再把查處的數據插進新表,不過這種複製表的方法,雖不能複製原表的相關約束條件,但是對於not null 卻是可以的,可以查看下面的例子:
orcl@ SCOTT> desc emp1
 Name                                                              Null?    Type
 ----------------------------------------------------------------- -------- --------------------------------------------
 EMPNO                                                                      NUMBER(4)
 ENAME                                                                      VARCHAR2(10)
 JOB                                                                        VARCHAR2(9)
 MGR                                                                        NUMBER(4)
 HIREDATE                                                                   DATE
 SAL                                                                        NUMBER(7,2)
 COMM                                                                       NUMBER(7,2)
 DEPTNO                                                                     NUMBER(2)
 
orcl@ SCOTT> alter table emp1 modify(sal not null);
 
Table altered.
 
Elapsed: 00:00:02.47
orcl@ SCOTT> desc emp1
 Name                                                              Null?    Type
 ----------------------------------------------------------------- -------- --------------------------------------------
 EMPNO                                                                      NUMBER(4)
 ENAME                                                                      VARCHAR2(10)
 JOB                                                                        VARCHAR2(9)
 MGR                                                                        NUMBER(4)
 HIREDATE                                                                   DATE
 SAL                                                               NOT NULL NUMBER(7,2)
 COMM                                                                       NUMBER(7,2)
 DEPTNO                                                                     NUMBER(2)
 
orcl@ SCOTT> 
orcl@ SCOTT> 
orcl@ SCOTT> 
orcl@ SCOTT> 
orcl@ SCOTT> create table emp2 as select * from emp1;
 
Table created.
 
Elapsed: 00:00:01.04
orcl@ SCOTT> desc emp2
 Name                                                              Null?    Type
 ----------------------------------------------------------------- -------- --------------------------------------------
 EMPNO                                                                      NUMBER(4)
 ENAME                                                                      VARCHAR2(10)
 JOB                                                                        VARCHAR2(9)
 MGR                                                                        NUMBER(4)
 HIREDATE                                                                   DATE
 SAL                                                               NOT NULL NUMBER(7,2)
 COMM                                                                       NUMBER(7,2)
 DEPTNO                                                                     NUMBER(2)
 
orcl@ SCOTT> 
orcl@ SCOTT> 
orcl@ SCOTT>                                                       
-----所以在工作中,如果我們需要創建一張和原表一模一樣的新表,並且要繼承原表所有的約束和默認值,我們除了可以用plsql/dev/工具導出建表語句之外,
     還可以採用oracle自帶函數來獲取建表語句,然後稍加修改就一切ok
orcl@ SCOTT> 
orcl@ SYS> conn scott/tiger
Connected.
orcl@ SCOTT> select dbms_metadata.get_ddl('TABLE','EMP') from dual;
 
DBMS_METADATA.GET_DDL('TABLE','EMP')
--------------------------------------------------------------------------------
 
  CREATE TABLE "SCOTT"."EMP"
   (    "EMPNO" NUMBER(4,0),
        "ENAME" VARCHAR2(10),
        "JOB" VARCHAR2(9),
        "MGR" NUMBER(4,0),
        "HIREDATE" DATE,
        "SAL" NUMBER(7,2),
        "COMM" NUMBER(7,2),
        "DEPTNO" NUMBER(2,0),
         CONSTRAINT "PK_EMP" PRIMARY KEY ("EMPNO")
  USING INDEX PCTFREE 10 INITRANS 2 MAXTRANS 255 COMPUTE STATISTICS
  STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
  PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT)
  TABLESPACE "USERS"  ENABLE,
         CONSTRAINT "FK_DEPTNO" FOREIGN KEY ("DEPTNO")
          REFERENCES "SCOTT"."DEPT" ("DEPTNO") ENABLE
   ) PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 NOCOMPRESS LOGGING
  STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
  PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT)
  TABLESPACE "USERS" ENABLE ROW MOVEMENT
 
 
 
Elapsed: 00:00:00.24
orcl@ SCOTT>                                                                     
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章