Oracle Xmltype型別淺析

ocpDBAboy發表於2015-06-15

 

Oracle中,我們對於檔案等複雜而且大體積的資料物件通常選擇使用lob型別系列變數。Lob型別對於檔案等複雜物件是一種不錯的儲存選擇。為了實現對XML資料檔案的儲存支援和操作支援,Oracle提供了資料型別xmltype作為XML資料的特殊儲存型別。Xmltype提供了適合的儲存、檢索和操作的支援,本篇就簡單介紹一下xmltype的一些特性。

 

 

1xml格式使用

 

定義一個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上,xmltypeOracle 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,'ddd');

1 row inserted

 

SQL> commit;

Commit complete

 

SQL> select * from t;

        ID CL

---------- --------------------------------------------------------------------------------

         1 ddd

 

 

可見,對於不合乎基本XML格式的資料,Oracle是不允許進行儲存的。

 

2XMLTYPELOB

 

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的結構型別。作為xmltypeOracle會在資料表上建立一個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/,如需轉載,請註明出處,否則將追究法律責任。

相關文章