對與一個DBA來說,create table ..as ..語句的使用應該是最平常不過的了,使用這個方法創建表的速度是速度是最快的,
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>
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.