Oracle Xmltype型別淺析
在Oracle中,我們對於檔案等複雜而且大體積的資料物件通常選擇使用lob型別系列變數。Lob型別對於檔案等複雜物件是一種不錯的儲存選擇。為了實現對XML資料檔案的儲存支援和操作支援,Oracle提供了資料型別xmltype作為XML資料的特殊儲存型別。Xmltype提供了適合的儲存、檢索和操作的支援,本篇就簡單介紹一下xmltype的一些特性。
1、xml格式使用
定義一個xmltype資料列表同一般的資料列沒有過多的差異。我們選擇Oracle 10gR2作為實驗環境。
SQL> select * from v$version;
BANNER
----------------------------------------------------------------
Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - Prod
PL/SQL Release 10.2.0.1.0 - Production
CORE 10.2.0.1.0 Production
TNS for 32-bit Windows: Version 10.2.0.1.0 - Production
NLSRTL Version 10.2.0.1.0 – Production
我們可以將資料列定義為xmltype上,xmltype在Oracle 10g中是作為專門的儲存XML格式。
SQL> create table t (id number, cl xmltype);
Table created
SQL> desc t;
Name Type Nullable Default Comments
---- ------- -------- ------- --------
ID NUMBER Y
CL XMLTYPE Y
資料欄位定義為xmltype之後,在進行資料儲存過程中都會進行格式檢查,當不合乎XML通用規則資料嘗試儲存入系統時,Oracle都會報錯。
SQL> insert into t values (1,'ddd');
insert into t values (1,'ddd')
ORA-31011: XML 語法分析失敗
ORA-19202: XML 處理
LPX-00210: 預期為 '而不是 'd'
Error at line 1
時出錯
SQL> insert into t values (1,'
1 row inserted
SQL> commit;
Commit complete
SQL> select * from t;
ID CL
---------- --------------------------------------------------------------------------------
1
可見,對於不合乎基本XML格式的資料,Oracle是不允許進行儲存的。
2、XMLTYPE與LOB
Xmltype欄位的是可以容納入XML格式檔案,那麼該型別欄位的本質是什麼呢?
SQL> select segment_name, segment_type, tablespace_name from user_segments;
SEGMENT_NAME SEGMENT_TYPE TABLESPACE_NAME
------------------------------ ------------------ ------------------------------
SYS_LOB0000056127C00003$$ LOBSEGMENT USERS
T TABLE USERS
SYS_IL0000056127C00003$$ LOBINDEX USERS
9 rows selected
SQL> select table_name, column_name,SEGMENT_NAME, TABLESPACE_NAME, INDEX_NAME from user_lobs;
TABLE_NAME COLUMN_NAME SEGMENT_NAME TABLESPACE INDEX_NAME
---------- -------------------- ------------------------------ ---------- ------------------------------
T SYS_NC00003$ SYS_LOB0000056127C00003$$ USERS SYS_IL0000056127C00003$$
我們發現,資料表T中多出了一個Lob資料段和Lob索引段,這個特性與LOB型別資料特性相同。值得關注的是在user_lobs中,顯示的column_name是一個未知的名稱“SYS_NC00003$”。那麼我們就繼續從這個線索入手。
我們需要檢查一下基礎後設資料表資訊。
SQL> select object_id, data_object_id from dba_objects where wner='SCOTT' and object_name='T';
OBJECT_ID DATA_OBJECT_ID
---------- --------------
56136 56139
SQL> select col#, segcol#, segcollength, name, type#,charsetform. from col$ where obj#=56136;
COL# SEGCOL# SEGCOLLENGTH NAME TYPE# CHARSETFORM
---------- ---------- ------------ -------------------- ---------- -----------
1 1 22 ID 2 0
2 0 2000 CL 58 0
2 2 4000 SYS_NC00003$ 112 1
對SYS_NC00003$列,我們根據charsetform欄位的取值,可以確定具體型別。
//片段來自dba_tab_cols檢視定義;
112, decode(c.charsetform, 2, 'NCLOB', 'CLOB'),
由此,我們可以基本猜想出xmltype的結構型別。作為xmltype,Oracle會在資料表上建立一個clob型別的系統列,用於協助儲存資料。
3、資料表定義
我們研究lob型別,在定義資料表的時候是有專門的lob(xxx)子句用於指定lob的一些儲存資訊。而在xmltype中,也存在這樣的介面方式嗎?我們使用dbms_metadata包抽取出資料表的後設資料資訊。
CREATE TABLE "SCOTT"."T"
( "ID" NUMBER,
"CL" "SCOTT"."XMLTYPE"
) 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"
XMLTYPE COLUMN "CL" STORE AS CLOB (
TABLESPACE "USERS" ENABLE STORAGE IN ROW CHUNK 8192 PCTVERSION 10
NOCACHE LOGGING
STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT)) ;
注意,此處是使用xmltype column xx store as clob子句進行定義。後面的關於storage的內容都是針對虛擬Lob列段物件而言的。
這裡,我們反過來想,如果我們使用xmltype column子句,是不是也可以在定義資料表的過程就將Lob與資料表儲存分開,放置在不同的表空間裡。
4、建立xmltype表到不同表空間
藉助xmltype column子句,我們可以實現在資料表建表階段,就將Lob相關段和資料表分開。
SQL> create table t (id number, cl xmltype) tablespace users XMLTYPE COLUMN "CL" STORE AS CLOB (tablespace example);
Table created
SQL> select segment_name, segment_type, tablespace_name from user_segments;
SEGMENT_NAME SEGMENT_TYPE TABLESPACE
------------------------------ ------------------ ----------
T TABLE USERS
SYS_IL0000056132C00003$$ LOBINDEX EXAMPLE
SYS_LOB0000056132C00003$$ LOBSEGMENT EXAMPLE
9 rows selected
SQL> select table_name, column_name,SEGMENT_NAME, TABLESPACE_NAME, INDEX_NAME from user_lobs;
TABLE_NAME COLUMN_NAME SEGMENT_NAME TABLESPACE INDEX_NAME
---------- -------------------- ------------------------------ ---------- ------------------------------
T SYS_NC00003$ SYS_LOB0000056132C00003$$ EXAMPLE SYS_IL0000056132C00003$$
如我們所希望的,資料表和Lob段(資料段和索引段)分別放置在了不同表空間裡。
5、資料表Move操作
資料表move操作可以實現將資料表段和相關段物件轉移到其他表空間或者收縮的作用。對包含xmltype列的資料表,move操作效果如何呢?
SQL> select segment_name, segment_type, tablespace_name from user_segments;
SEGMENT_NAME SEGMENT_TYPE TABLESPACE
------------------------------ ------------------ ----------
T TABLE USERS
SYS_LOB0000056136C00003$$ LOBSEGMENT USERS
SYS_IL0000056136C00003$$ LOBINDEX USERS
9 rows selected
SQL> alter table t move tablespace example;
Table altered
SQL> select segment_name, segment_type, tablespace_name from user_segments;
SEGMENT_NAME SEGMENT_TYPE TABLESPACE
------------------------------ ------------------ ----------
SYS_LOB0000056136C00003$$ LOBSEGMENT USERS
SYS_IL0000056136C00003$$ LOBINDEX USERS
T TABLE EXAMPLE
9 rows selected
發現在Oracle 10g下,如果單純的使用move命令,段效果變化同一般的lob型別是一樣的。資料表T移動到了新的表空間位置,而對應的lob段沒有變化。同時,還要注意,lob索引的狀態保持valid狀態。
SQL> select index_name, index_type, table_name, status from user_indexes where table_owner='SCOTT' and table_name='T';
INDEX_NAME INDEX_TYPE TABLE_NAME STATUS
------------------------------ --------------------------- ---------- --------
SYS_IL0000056136C00003$$ LOB T VALID
如果我們嘗試使用move lob命令會如何呢?
//普通呼叫無效,因為cl不是一個lob型別;
sQL> alter table t move lob(cl) store as xmlseg tablespace example;
alter table t move lob(cl) store as xmlseg tablespace example
ORA-00904: "CL": 識別符號無效
//嘗試移動隱含列物件;
SQL> alter table t move lob(SYS_NC00003$) store as mt (tablespace example);
Table altered
SQL> select segment_name, segment_type, tablespace_name from user_segments;
SEGMENT_NAME SEGMENT_TYPE TABLESPACE_NAME
------------------------------ ------------------ ------------------------------
T TABLE EXAMPLE
SYS_IL0000056136C00003$$ LOBINDEX EXAMPLE
MT LOBSEGMENT EXAMPLE
從上面的實驗中,我們可以看出:當我們對lob進行move的時候,如果使用資料列(xmltype),資料操作是不支援的。換而使用對隱含列的操作時,可實現對一個已經建立資料表的Lob段進行移動。
注意:當我們使用到Oracle 11g的時候,事情有所差異。
SQL> select * from v$version;
BANNER
--------------------------------------------------------------------------------
Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - Production
PL/SQL Release 11.2.0.1.0 - Production
CORE 11.2.0.1.0 Production
TNS for Linux: Version 11.2.0.1.0 - Production
NLSRTL Version 11.2.0.1.0 - Production
我們在11g上進行試驗。
SQL> create table t (id number, cl xmltype) tablespace system;
Table created
SQL> select segment_name, segment_type, tablespace_name from user_segments;
SEGMENT_NAME SEGMENT_TYPE TABLESPACE
------------------------------ ------------------ ----------
T TABLE SYSTEM
SYS_IL0000075364C00003$$ LOBINDEX SYSTEM
SYS_LOB0000075364C00003$$ LOBSEGMENT SYSTEM
9 rows selected
此時,我們進行move操作。
SQL> alter table t move tablespace users;
Table altered
SQL> select segment_name, segment_type, tablespace_name from user_segments;
SEGMENT_NAME SEGMENT_TYPE TABLESPACE
------------------------------ ------------------ ----------
T TABLE USERS
SYS_IL0000075364C00003$$ LOBINDEX USERS
SYS_LOB0000075364C00003$$ LOBSEGMENT USERS
9 rows selected
可以看到,在11g裡進行move操作的時候,資料表和XmlType Lob段做到同時移動。
那麼move是否有如10g特性呢?
SQL> select object_id, data_object_id, object_name from dba_objects where object_name='T' and wner='SCOTT';
OBJECT_ID DATA_OBJECT_ID OBJECT_NAME
---------- -------------- -------------
75364 75367 T
隱藏虛擬列資訊如下:
SQL> select * from col$ where obj#=75364;
OBJ# COL# SEGCOL# SEGCOLLENGTH OFFSET NAME TYPE#
---------- ---------- ---------- ------------ ---------- -------------------- ----------
75364 1 1 22 0 ID 2
75364 2 0 2000 0 CL 58
75364 2 2 4000 0 SYS_NC00003$ 112
對lob段進行move操作。
SQL> alter table t move lob(SYS_NC00003$) store as xmlseg (tablespace system);
Table altered
SQL> select segment_name, segment_type, tablespace_name from user_segments;
SEGMENT_NAME SEGMENT_TYPE TABLESPACE_NAME
------------------------------ ------------------------------ ------------------------------
T TABLE USERS
SYS_IL0000075364C00003$$ LOBINDEX SYSTEM
XMLSEG LOBSEGMENT SYSTEM
9 rows selected
對內部列的操作,成功的在11g中實現將lob段移動到其他表空間裡。
6、結論
XMLtype型別是我們儲存XML格式檔案一種可選的格式型別,提供了各種針對於xml文件的操作和檢索。本篇著重分析了Xmltype型別的儲存特性和差異。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/29267792/viewspace-1700619/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- Oracle Lob型別儲存淺析Oracle型別
- Oracle基本資料型別儲存格式淺析——RAW型別Oracle資料型別
- Timestamp型別淺析型別
- Oracle基本資料型別儲存格式淺析(五)——RAW型別Oracle資料型別
- Oracle基本資料型別儲存格式淺析(四)——ROWID型別Oracle資料型別
- Oracle基本資料型別儲存格式淺析(三)——日期型別(一)Oracle資料型別
- Oracle基本資料型別儲存格式淺析(三)——日期型別(二)Oracle資料型別
- Oracle基本資料型別儲存格式淺析(三)——日期型別(三)Oracle資料型別
- Oracle基本資料型別儲存格式淺析(三)——日期型別(四)Oracle資料型別
- 淺析number型別的值型別
- 淺析NAT的型別-ZT型別
- Oracle基本資料型別儲存格式淺析[zt]Oracle資料型別
- Oracle基本資料型別儲存格式淺析(二)——數字型別Oracle資料型別
- 淺析Kubernrtes服務型別(Service Types)型別
- JavaScript的隱式型別轉換淺析JavaScript型別
- JAVA泛型淺析Java泛型
- JavaScript 隱性型別轉換步驟淺析JavaScript型別
- java多型性淺析Java多型
- oracle的TAF淺析Oracle
- Java泛型應用淺析Java泛型
- 淺析Oracle(rownum)和Mysql(limit)分頁的區別OracleMySqlMIT
- 淺談oracle複合資料型別Oracle資料型別
- impdp匯入包含xmltype型別欄位空表報錯問題XML型別
- 淺談oracle複合資料型別 (1)Oracle資料型別
- 淺談oracle複合資料型別 (2)Oracle資料型別
- SQL Server中datetimeset轉換datetime型別問題淺析SQLServer型別
- 淺析多媒體互動展廳幾個常見型別型別
- ORACLE關閉過程淺析Oracle
- ORACLE啟動過程淺析Oracle
- Oracle相關NUMA特性淺析Oracle
- Oracle 12c PDB淺析Oracle
- 淺析mybatis中${}和#{}取值區別MyBatis
- Oracle 12c PDB淺析(二)Oracle
- oracle的resetlogs機制淺析Oracle
- MySQL bit型別增加索引後查詢結果不正確案例淺析MySql型別索引
- 淺析MySQL InnoDB的隔離級別MySql
- impdp匯入XMLTYPE欄位型別的資料出現亂碼的問題XML型別
- 淺談程式語言型別的強型別,弱型別,動態型別,靜態型別型別