阿里云-云小站(无限量代金券发放中)
【腾讯云】云服务器、云数据库、COS、CDN、短信等热卖云产品特惠抢购

Oracle Xmltype类型浅析

183次阅读
没有评论

共计 8500 个字符,预计需要花费 22 分钟才能阅读完成。

在 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,’ddd’);

1 row inserted

SQL> commit;

Commit complete

SQL> select * from t;

        ID CL

———- ——————————————————————————–

        1 ddd

可见,对于不合乎基本 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 类型的存储特性和差异。

更多 Oracle 相关信息见 Oracle 专题页面 http://www.linuxidc.com/topicnews.aspx?tid=12

本文永久更新链接地址 :http://www.linuxidc.com/Linux/2017-03/141678.htm

正文完
星哥玩云-微信公众号
post-qrcode
 0
星锅
版权声明:本站原创文章,由 星锅 于2022-01-22发表,共计8500字。
转载说明:除特殊说明外本站文章皆由CC-4.0协议发布,转载请注明出处。
【腾讯云】推广者专属福利,新客户无门槛领取总价值高达2860元代金券,每种代金券限量500张,先到先得。
阿里云-最新活动爆款每日限量供应
评论(没有评论)
验证码
【腾讯云】云服务器、云数据库、COS、CDN、短信等云产品特惠热卖中