3 Oracle XML DBの使用方法の概要
Oracle XML DBの様々な使用方法の概要について説明します。
この概要では、XMLType
表および列の作成およびパーティション化、データ整合性の適用、データベースXMLコンテンツのロード、問合せおよび更新、リレーショナル・データからのXMLデータの生成を行う方法について説明します。また、XML文書で使用するキャラクタ・セットをOracle XML DBが判断する方法についても説明します。
主なXML Schema機能を示す発注書
この章の例の多くでは、発注書のXMLコンテンツへのアクセスおよび管理の方法を示します。発注書は高度に構造化された文書ですが、ほとんど構造化されていないXML文書に対しても、ここに示す方法を使用することができます。
ここで例として使用する発注書は、次のような一般的なXML文書の主要な機能を示す発注書XML Schemaに準拠しています。
-
グローバル要素
PurchaseOrder
は、complexType
PurchaseOrderType
のインスタンスです。 -
PurchaseOrderType
では、PurchaseOrder
要素を構成する一連のノードが定義されます。 -
LineItem
要素は、LineItems
要素のコレクションで構成されます。 -
各
LineItem
要素は、2つの要素(Description
およびPart
)で構成されます。 -
Part
要素には、属性Id
、Quantity
およびUnitPrice
があります。
- XMLType表および列の作成
XMLTypeは抽象データ型であるため、XMLType
表または列は容易に作成できます。 - バイナリXMLとして格納されたXMLTypeデータでの仮想列の作成
仮想列は、バイナリXMLとして格納されているXMLType
データに対してのみ作成できます。このような列は、データのパーティション化および制約に役立ちます。 - バイナリXMLとして格納されたXMLTypeデータが含まれる表のパーティション化
バイナリXMLとして格納されたXMLType
データが含まれる表をパーティション化できます。 - データベースを使用したXMLデータ整合性の規定
SQLおよびXMLの能力と、ルールを適用するデータベースの機能を組み合せることができます。 - Oracle XML DBへのXMLコンテンツのロード
XMLコンテンツをOracle XML DBにロードする方法は複数あります。 - Oracle XML DBに格納されたXMLコンテンツの問合せ
Oracle XML DBのXMLコンテンツを問い合せて取得する方法は多数あります。 - Oracle XML DBに格納されたXMLコンテンツの更新
XMLコンテンツを更新する場合は、文書のコンテンツ全体または文書の特定部分のみを置換できます。 - リレーショナル・データからのXMLデータの生成
Oracle XML DBを使用して、リレーショナル・データからXMLデータを生成できます。 - XML文書のキャラクタ・セット
XML文書で使用するキャラクタ・セットをOracle XML DBが決定する方法はいくつかあります
関連項目:
-
ほとんどの用途に推奨されるOracle XML DB機能は、Oracle XML DBのアプリケーション設計に関する考慮事項を参照してください。
-
Oracle XML DBのより高度な機能の詳細は、XMLType API、XML Schemaとオブジェクト・リレーショナルXMLTypeおよびOracle XML DBリポジトリを参照してください。
-
この章の例で使用される発注書XML Schemaについては、発注書XML Schemaを参照してください。
親トピック: Oracle XML DBの基礎
3.1 XMLType表および列の作成
XMLTypeは抽象データ型であるため、XMLType
表または列は容易に作成できます。
記憶域オプションとXML Schemaを指定しない基本的なCREATE TABLE
文では、XMLType
データはバイナリXMLとして格納されます。脚注 1
例3-1 XMLType列を含む表の作成
CREATE TABLE mytable1 (key_column VARCHAR2(10) PRIMARY KEY, xml_column XMLType);
例3-2 XMLType表の作成
CREATE TABLE mytable2 OF XMLType;
親トピック: Oracle XML DBの使用方法の概要
3.2 バイナリXMLとして格納されたXMLTypeデータでの仮想列の作成
仮想列は、バイナリXMLとして格納されているXMLType
データに対してのみ作成できます。このような列は、データのパーティション化および制約に役立ちます。
XMLデータの仮想列は他のデータ型の場合と同じ方法で作成できますが、若干異なる構文を使用します。(特に、列定義に関連付けて制約を指定することができません。)
XML要素または属性に基づく仮想列を作成するには、その要素や属性を含むSQL式によって仮想列を定義します。したがって、作成される列はファンクション・ベースです。
これには、例3-3
および例3-4
に示すように、SQL/XML関数XMLCastおよびXMLQueryを使用します。関数XMLQuery
のXQuery式引数は、子および属性の軸のみを使用する簡単なXPath式にする必要があります。
例3-3では、バイナリXMLとして格納されるXMLType
表po_binaryxml
を作成しています。属性/PurchaseOrder/@orderDate
内のXMLデータを表す仮想列date_col
を作成しています。
例3-4では、主キー用のVARCHAR2
列key_col
とXMLデータ用のXMLType
列xml_col
という2つの列を持つリレーショナル表rel_tab
を作成しています。
XMLType
は抽象データ型なので、仮想列をXMLType
表または列に作成する場合、それらの列は非表示になります。これらはDESCRIBE
文などに表示されません。表示されないことで、DESCRIBE
などの操作を使用するツールが、仮想列に惑わされずに正常に機能することができます。
注意:
時間隔パーティション化に仮想列を使用する場合は、そのデータ型がNUMBER
またはDATE
である必要があり、そうでない場合、エラーが発生します。SQL/XML関数XMLCast
およびXMLQuery
を使用して、適切なデータ型にキャストします。
関連項目:
仮想列を使用した表の作成の詳細は、Oracle Database SQL言語リファレンスを参照してください。
例3-3 XMLType表内のXML属性の仮想列の作成
CREATE TABLE po_binaryxml OF XMLType
XMLTYPE STORE AS BINARY XML
VIRTUAL COLUMNS
(date_col AS (XMLCast(XMLQuery('/PurchaseOrder/@orderDate'
PASSING OBJECT_VALUE RETURNING CONTENT)
AS DATE)));
例3-4 XMLType列内のXML属性の仮想列の作成
CREATE TABLE reltab (key_col VARCHAR2(10) PRIMARY KEY,
xml_col XMLType)
XMLTYPE xml_col STORE AS BINARY XML
VIRTUAL COLUMNS
(date_col AS (XMLCast(XMLQuery('/PurchaseOrder/@orderDate'
PASSING xml_col RETURNING CONTENT)
AS DATE)));
3.3 バイナリXMLとして格納されたXMLTypeデータが含まれる表のパーティション化
バイナリXMLとして格納されたXMLType
データが含まれる表をパーティション化できます。
2つの可能性があります。
-
表は、
XMLType
列および非XMLType
列を持つリレーショナル形式です。 -
表は、データ型
XMLType
です。
XMLType
列の場合、非XMLType
列をパーティション化キーとして使用します。例3-5で説明します。
この例では、XMLデータに関して新しいことや特別なことは示されていません。列の1つにXMLType
データが含まれることは重要ではありません。異なるのは他のこと、つまり、XMLType
表がパーティション化されていることです。
XMLデータには独自の構造がありますが、(XMLType
のオブジェクト・リレーショナル記憶域を除き)、データベースのデータ構造には直接反映されません。バイナリXMLとして格納されたXMLType
データの場合、個別のXML要素および属性がデータベースの個別の列や表にマップされることはありません。
したがって、個別の要素や属性の値に応じてバイナリXMLデータをパーティション化する場合、リレーショナル・データの標準的な手法は適用できません。このため、対象のXMLデータを表す仮想列を作成してから、その仮想列を使用して必要な制約またはパーティションを定義する必要があります。
手順は次のとおりです。
-
目的のXML要素または属性に対応する仮想列を定義します。
-
その列を使用して、
XMLType
データを一括してパーティション化します。
これは例3-6で説明されています。仮想列date_col
は、発注書の要素PurchaseOrder
のorderDate
属性をターゲットにしています。この列は、パーティション化キーとして使用されています。
XMLデータが含まれるパーティション化表を使用して最適なパフォーマンスを実現するには、XMLType
表ではなくXMLType
列を使用し、これにより、非XMLType
列を使用してパーティション化することをお薦めします。
注意:
-
仮想列を使用して
XMLType
表をパーティション化できるのは、記憶域モデルがバイナリXMLである場合のみです。レンジ、ハッシュおよびリストのパーティション化がサポートされています。 -
XMLとして格納された
XMLType
表のパーティション化は、11gリリース2 (11.2)以降でサポートされます。データベースの互換性(ファイルinit.ora
内のパラメータcompatible
)が11.2以上の場合にのみサポートされます。 -
リレーショナル表に
XMLType
列が含まれる場合、XMLデータの仮想列を定義する列を使用して表をパーティション化することはできません。
例3-5 XMLType列を持つリレーショナル表のパーティション化
CREATE TABLE reltab (key_col VARCHAR2(10) PRIMARY KEY,
xml_col XMLType)
XMLTYPE xml_col STORE AS BINARY XML
PARTITION BY RANGE (key_col)
(PARTITION P1 VALUES LESS THAN ('abc'),
PARTITION P2 VALUES LESS THAN (MAXVALUE));
例3-6 XMLType表のパーティション化
CREATE TABLE po_binaryxml OF XMLType
XMLTYPE STORE AS BINARY XML
VIRTUAL COLUMNS
(date_col AS (XMLCast(XMLQuery('/PurchaseOrder/@orderDate'
PASSING OBJECT_VALUE RETURNING CONTENT)
AS DATE)))
PARTITION BY RANGE (date_col)
(PARTITION orders2001 VALUES LESS THAN (to_date('01-JAN-2002')),
PARTITION orders2002 VALUES LESS THAN (MAXVALUE));
3.4 データベースを使用したXMLデータ整合性の規定
SQLおよびXMLの能力と、ルールを適用するデータベースの機能を組み合せることができます。
XML Schemaによって提供される機能を補完するために、SQLを使用できます。XMLType
表または列に格納できるのは、整形式のXML文書のみです。整形式のXML文書とは、XML宣言で宣言されたXMLバージョンの構文に準拠しているXML文書です。これには、ルート要素が単一か、タグが適切にネストされているかなどが含まれます。さらに、XMLType
表または列がXML Schemaに制限される場合、その表または列に格納できるのはXML Schemaに準拠する文書のみです。これ以外のXML文書をXML Schemaに基づくXMLType
に格納または挿入しようとすると、エラーが発生します。例3-7に、これを示します。
このようなエラーは、コンテンツが直接XMLType
表に挿入されるときにのみ発生します。Oracle XML DBが、XML Schemaにより定義されたクラスのメンバーとして文書を認識していなかったことを示します。スキーマにより定義されたクラスのメンバーとして認識される文書は、次の条件を満たしている必要があります。
-
XML文書のルート要素の名前が、
XMLType
表または列の定義で使用するグローバル要素の名前と一致する必要があります。 -
XML文書に
XMLSchema-instance
名前空間の適切な属性が含まれているか、またはXMLType
コンストラクタかXMLType
のcreateSchemaBasedXML()
メソッドを使用してXML文書がXML Schemaに明示的に関連付けられている必要があります。
制限されているXML SchemaでtargetNamespace
が宣言されている場合、インスタンス・ドキュメントには、XML Schemaで定義されたtargetNamespace
に文書のルート要素を配置するための適切な名前空間宣言が含まれている必要があります。
注意:
XMLによる制限は、個々のXML文書内で適用されます。データベース(SQL)による制限は、一連のXML文書にわたって適用されます。
例3-7 不適切なXML文書を挿入しようとした場合に発生するエラー
INSERT INTO purchaseorder
VALUES (XMLType(bfilename('XMLDIR', 'Invoice.xml'), nls_charset_id('AL32UTF8')))
VALUES (XMLType(bfilename('XMLDIR', 'Invoice.xml'), nls_charset_id('AL32UTF8')))
*
ERROR at line 2:
ORA-19007: Schema - does not match expected
http://localhost:8080/source/schemas/poSource/xsd/purchaseOrder.xsd.
- SQL制約を使用した参照整合性の規定
SQL制約およびデータベース・トリガーを使用して、一意性と外部キーの関係など、データ整合性プロパティを保証できます。
関連トピック
親トピック: Oracle XML DBの使用方法の概要
3.4.1 SQL制約を使用した参照整合性の規定
SQL制約およびデータベース・トリガーを使用して、一意性と外部キーの関係など、データ整合性プロパティを保証できます。
W3CのXML Schema勧告では、XML文書のコンテンツを定義するための強力な言語が定義されています。ただし、現在はW3CのXML Schema勧告で扱われていない簡単なデータ管理の概念がいくつかあります。たとえば、要素または属性の値が次のいずれかのプロパティを持っているかを確認できることなどです。
-
XML文書のセット間で一意であること(
UNIQUE
制約) -
現在の文書以外の特定のデータ・ソース内に存在していること(
FOREIGN KEY
制約)
ただし、Oracle XML DBでは、そうした制約を強制的に適用できます。XMLデータで整合性を規定するために使用するメカニズムは、リレーショナル・データで整合性を規定するためのメカニズムと同じです。一意性と外部キーの関係などの簡単なルールは、SQL制約を指定することによって規定できます。複雑なルールは、データベース・トリガーを指定して規定できます。
Oracle XML DBを使用すると、XML Schema構造体を使用して指定できるルールに加え、データベースを使用して、ビジネス・ルールもXMLコンテンツに実施することができます。データベースでは、XMLが表に直接挿入されているか、Oracle XML DBリポジトリでサポートされているプロトコルの1つを使用してアップロードされているかに関係なく、これらのビジネス・ルールを規定します。
XMLデータには独自の構造がありますが、(XMLType
のオブジェクト・リレーショナル記憶域を除き)、データベースのデータ構造には直接反映されません。バイナリXMLとして格納されたXMLType
データの場合、個別のXML要素および属性がデータベースの個別の列や表にマップされることはありません。
したがって、個別の要素や属性の値に応じてバイナリXMLデータを制約する場合、リレーショナル・データの標準的な手法は適用できません。このため、対象のXMLデータを表す仮想列を作成してから、その仮想列を使用して必要な制約を定義する必要があります。
手順は次のとおりです。
-
目的のXML要素または属性に対応する仮想列を定義します。
-
その列を使用して、
XMLType
データを一括して制約します。
バイナリXMLデータは、XMLType
表またはリレーショナル表のXMLType
列に含まれる場合があります。前者の場合、必要に応じて、制約の作成をCREATE TABLE
文の一部として含めることができます。後者の場合、リレーショナル表が作成された後、ALTER TABLE
文を使用して制約を作成する必要があります。
例3-8 仮想列を使用したバイナリXML表の制約
この例では、XMLType
表の場合の方法を示しています。ここでは、発注書のReference
要素を使用して、仮想列c_xtabref
を定義しています。この列に、表に格納されたすべての文書間でノード/PurchaseOrder/Reference/text()
の値が一意であることを保証する一意性制約reference_is_unique
を定義しています。表にはOE.purchaseorder
のデータが入力されています。次に、重複文書DuplicateReference.xml
を挿入しようとしますが、これは一意性制約に違反し、エラーが発生しています。
CREATE TABLE po_binaryxml OF XMLType (CONSTRAINT reference_is_unique UNIQUE (c_xtabref)) XMLTYPE STORE AS BINARY XML VIRTUAL COLUMNS (c_xtabref AS (XMLCast(XMLQuery('/PurchaseOrder/Reference' PASSING OBJECT_VALUE RETURNING CONTENT) AS VARCHAR2(32)))); INSERT INTO po_binaryxml SELECT OBJECT_VALUE FROM OE.purchaseorder; 132 rows created. INSERT INTO po_binaryxml VALUES (XMLType(bfilename('XMLDIR', 'DuplicateReference.xml'), nls_charset_id('AL32UTF8'))); INSERT INTO po_binaryxml * ERROR at line 1: ORA-00001: unique constraint (OE.REFERENCE_IS_UNIQUE) violated
例3-9 仮想列を使用したバイナリXML列の制約: 一意性
この例では、リレーショナル表のXMLType
列の場合の方法を示しています。ここでは、仮想列c_xcolref
、および例3-8
で定義した一意性制約を参照するfk_refを定義しています。例3-8の場合のように、これは、XMLType
列po_binxml_col
に格納されたすべての文書間でノード/PurchaseOrder/Reference/text()
の値が一意であることを保証しています。
この例では、XMLType
列にOE.purchaseorder
の同じデータが入力されています。次に、重複文書DuplicateReference.xml
を挿入しようとしますが、これは一意性制約に違反し、エラーが発生しています。
CREATE TABLE po_reltab (po_binxml_col XMLType) XMLTYPE po_binxml_col STORE AS BINARY XML VIRTUAL COLUMNS (c_xcolref AS (XMLCast (XMLQuery('/PurchaseOrder/Reference' PASSING po_binxml_col RETURNING CONTENT) AS VARCHAR2(32)))); ALTER TABLE po_reltab ADD CONSTRAINT reference_is_unique UNIQUE (c_xcolref)); INSERT INTO po_reltab SELECT OBJECT_VALUE FROM OE.purchaseorder; INSERT INTO po_reltab VALUES (XMLType(bfilename('XMLDIR', 'DuplicateReference.xml'), nls_charset_id('AL32UTF8'))); INSERT INTO po_reltab * ERROR at line 1: ORA-00001: unique constraint (OE.REFERENCE_IS_UNIQUE) violated
例3-10 仮想列を使用したバイナリXML列の制約: 外部キー
この例は例3-9と似ていますが、例3-8で定義した一意性制約を持つ列を参照する外部キー制約fk_ref
を使用しています。ここでは、ファイルDuplicateReference.xml
の文書の挿入は、この文書が表po_binaryxml
の(仮想)列c_tabref
内にあるため、成功しています。表po_binaryxml
内の文書と一致しない文書の挿入です。
CREATE TABLE po_reltab (po_binxml_col XMLType) XMLTYPE po_binxml_col STORE AS BINARY XML VIRTUAL COLUMNS (c_xcolref AS (XMLCast (XMLQuery('/PurchaseOrder/Reference' PASSING po_binxml_col RETURNING CONTENT) AS VARCHAR2(32)))); ALTER TABLE po_reltab ADD CONSTRAINT fk_ref FOREIGN KEY (c_xcolref) REFERENCES po_binaryxml(c_xtabref); INSERT INTO po_reltab VALUES (XMLType(bfilename('XMLDIR', 'DuplicateReference.xml'), nls_charset_id('AL32UTF8'))); INSERT INTO po_reltab VALUES ('<PurchaseOrder><Reference>Not Compliant</Reference></PurchaseOrder>'); INSERT INTO po_reltab VALUES ('<PurchaseOrder><Reference>Not Compliant </Reference></PurchaseOrder>') * ERROR at line 1: ORA-02291: integrity constraint (OE.FK_REF) violated - parent key not found
例3-11 FTPを使用してXMLをロードしたときのデータベース整合性の規定
XML Schemaに基づくXMLコンテンツがOracle XML DBリポジトリにロードされると、制約およびトリガーを使用して定義された整合性ルールも規定されます。この例では、XML Schemaに基づくXMLコンテンツが、FTPなどのプロトコルを使用してOracle XML DBリポジトリにアップロードされると、データベース整合性も適用されることを示します。この例では、一意性以外の別の制約も違反しています。
$ ftp localhost 2100
Connected to localhost.
220 mdrake-sun FTP Server (Oracle XML DB/Oracle Database 10g Enterprise Edition
Release 10.1.0.0.0 - Beta) ready.
Name (localhost:oracle10): QUINE
331 Password required for QUINE
Password: password
230 QUINE logged in
ftp> cd /source/schemas
250 CWD Command successful
ftp> put InvalidReference.xml
200 PORT Command successful
150 ASCII Data Connection
550- Error Response
ORA-00604: error occurred at recursive SQL level 1
ORA-31154: invalid XML document
ORA-19202: Error occurred in XML processing
LSX-00221: "SBELL-20021009" is too short (minimum length is 18)
ORA-06512: at "SYS.XMLTYPE", line 333
ORA-06512: at "QUINE.VALIDATE_PURCHASEORDER", line 3
ORA-04088: error during execution of trigger 'QUINE.VALIDATE_PURCHASEORDER'
550 End Error Response
ftp> put InvalidElement.xml
200 PORT Command successful
150 ASCII Data Connection
550- Error Response
ORA-30937: No schema definition for 'UserName' (namespace '##local') in parent
'PurchaseOrder'
550 End Error Response
ftp> put DuplicateReference.xml
200 PORT Command successful
150 ASCII Data Connection
550- Error Response
ORA-00604: error occurred at recursive SQL level 1
ORA-00001: unique constraint (QUINE.REFERENCE_IS_UNIQUE) violated
550 End Error Response
ftp> put InvalidUser.xml
200 PORT Command successful
150 ASCII Data Connection
550- Error Response
ORA-00604: error occurred at recursive SQL level 1
ORA-02291: integrity constraint (QUINE.USER_IS_VALID) violated - parent key not
found
550 End Error Response
プロトコルを使用して文書をアップロードしているときにエラーが発生すると、Oracle XML DBはクライアントに対して完全なSQLエラー・トレースを提供します。エラーの解析とレポートの方法は、クライアント・アプリケーションに組み込まれたエラー処理によって決まります。たとえば、コマンドラインFTPツールなどのクライアントはOracle XML DBから戻されたエラーをレポートし、Microsoft Windows Explorerなどのクライアントは単に汎用エラー・メッセージをレポートします。
3.5 Oracle XML DBへのXMLコンテンツのロード
XMLコンテンツをOracle XML DBにロードする方法は複数あります。
- SQLまたはPL/SQLを使用したXMLコンテンツのロード
- Javaを使用したXMLコンテンツのロード
JavaでDOMを使用してSQLXML
インスタンスをロードできます。 - Cを使用したXMLコンテンツのロード
CコードでDOMを使用してXMLType
インスタンスをロードできます。 - 小規模なXML文書を含む大規模なXMLファイルのロード
小規模なXML文書のコレクションで構成された大規模なXMLファイルをロードするときは、Simple API for XML(SAX)の解析機能を使用してファイルを一連の小規模な文書に分割してから文書を挿入すると、効率的にロードできます。 - SQL*Loaderを使用した大規模なXMLファイルのロード
SQL*Loaderを使用すると、大量のXMLデータをOracle Databaseにロードできます。 - DBMS_XDB_REPOSを使用したリポジトリへのXML文書のロード
PL/SQLパッケージDBMS_XDB_REPOS
を使用すると、XML文書をOracle XML DBリポジトリにロードできます。表ベースではなく、パスベースの方法でリポジトリの文書(リソース)にアクセスできます。 - プロトコルを使用したリポジトリへの文書のロード
文書は、XML文書を含め、一般的なプロトコルを使用して、ローカル・ファイル・システムからOracle XML DBリポジトリにロードできます。
親トピック: Oracle XML DBの使用方法の概要
3.5.1 SQLまたはPL/SQLを使用したXMLコンテンツのロード
SQLまたはPL/SQLの簡単なINSERT
操作を使用して、XML文書をデータベースにロードできます。
文書は、XMLType
列または表として格納する前に、XMLType
コンストラクタの1つを使用してXMLType
インスタンスに変換する必要があります。
XMLType
コンストラクタを使用すると、VARCHAR
、CLOB
およびBFILE
値を含む様々なソースからXMLType
インスタンスを作成できます。このコンストラクタは、XMLType
の作成に関連する処理量を減らす追加の引数を受け入れます。たとえば、ソースのXML文書が有効だとわかっている場合には、有効かどうかわからない場合に実行される型チェックを無効にする引数をコンストラクタに指定できます。
さらに、ソース・データがデータベース・キャラクタ・セットでエンコードされていない場合、XMLType
インスタンスはBFILE
値またはBLOB
値を使用して構成できます。ソース・データのエンコーディングは、コンストラクタのキャラクタ・セットID(csid
)引数で指定されます。
SQL INSERT
を使用して、コレクションを含む大規模な文書を(XMLType
列ではなく)XMLType
表に挿入する場合、Oracle XML DBによってロード時間とメモリー使用量が最適化されます。
例3-13に、XMLコンテンツをXMLType
表に挿入する方法を示します。この挿入を行う前に、処理するファイルが含まれたディレクトリを指すデータベース・ディレクトリ・オブジェクトを作成する必要があります。作成するためには、CREATE ANY DIRECTORY
権限が必要です。
関連項目:
-
XMLType
コンストラクタの詳細は、Oracle Database PL/SQLパッケージおよびタイプ・リファレンスを参照してください。 -
Oracle Database SQL言語リファレンスの
GRANT
を参照してください。
例3-12 データベース・ディレクトリの作成
CREATE DIRECTORY xmldir AS path_to_folder_containing_XML_file;
例3-13 XMLType表へのXMLコンテンツの挿入
INSERT INTO mytable2 VALUES (XMLType(bfilename('XMLDIR', 'purchaseOrder.xml'), nls_charset_id('AL32UTF8')));
nls_charset_id
に渡される値は、読み取られるファイルのエンコーディングがUTF-8であることを示します。
3.5.2 Javaを使用したXMLコンテンツのロード
JavaでDOMを使用してSQLXML
インスタンスをロードできます。
例3-14に、ドキュメント・オブジェクト・モデル(DOM)を指定して最初にJavaでSQLXML
インスタンスを作成することによって、XMLコンテンツをOracle XML DBにロードする方法を示します。
単純なバルク・ローダー・アプリケーションが、OTNのOracle XML DBで入手できます。これにはJava Database Connectivity (JDBC)を使用してXMLファイルのディレクトリをOracle XML DBにロードする方法が示されています。JDBCは、Oracle Databaseに対する一連のJavaインタフェースです。
例3-14 Javaを使用したXMLType表へのコンテンツの挿入
public void doInsert(Connection conn, Document doc)
throws Exception
{
String query = "INSERT INTO purchaseorder VALUES (?)";
SQLXML sx = conn.createSQLXML();
DOMResult dom = sx.setResult(DOMResult.class);
dom.setNode(doc);
PreparedStatement statement = conn.prepareStatement(query);
statement.setSQLXML(1, sx);
statement.execute();
}
親トピック: Oracle XML DBへのXMLコンテンツのロード
3.5.3 Cを使用したXMLコンテンツのロード
CコードでDOMを使用してXMLType
インスタンスをロードできます。
例3-15に、DOMを指定してXMLType
インスタンスを作成することによって、CコードでXMLコンテンツをXMLType
表に挿入する方法を示します(Oracle XML Developer's Kitプログラマーズ・ガイドを参照)。この例の完全なリストは、C (OCI)を使用したXMLデータのロードを参照してください。
注意:
この機能を簡単に説明するために、この例では、デプロイされたシステムで通常使用されるパスワード管理手法を実行していません。本番環境では、Oracle Databaseのパスワード管理ガイドラインに従い、サンプル・アカウントを無効にしてください。パスワード管理ガイドラインおよび他のセキュリティに関する推奨事項は、Oracle Databaseセキュリティ・ガイドを参照してください。
例3-15 Cを使用したXMLType表へのコンテンツの挿入
. . .
void main()
{
OCIType *xmltdo;
xmldocnode *doc;
ocixmldbparam params[1];
xmlerr err;
xmlctx *xctx;
oratext *ins_stmt;
sword status;
xmlnode *root;
oratext buf[10000];
/* Initialize envhp, svchp, errhp, dur, stmthp */
init_oci_connect();
/* Get an XML context */
params[0].name_ocixmldbparam = XCTXINIT_OCIDUR;
params[0].value_ocixmldbparam = &dur;
xctx = OCIXmlDbInitXmlCtx(envhp, svchp, errhp, params, 1);
if (!(doc = XmlLoadDom(xctx, &err, "file", filename,
"schema_location", schemaloc, NULL)))
{
printf("Parse failed.\n");
return;
}
else
printf("Parse succeeded.\n");
root = XmlDomGetDocElem(xctx, doc);
printf("The xml document is :\n");
XmlSaveDom(xctx, &err, (xmlnode *)doc, "buffer", buf, "buffer_length", 10000, NULL);
printf("%s\n", buf);
/* Insert the document into my_table */
ins_stmt = (oratext *)"insert into purchaseorder values (:1)";
status = OCITypeByName(envhp, errhp, svchp, (const text *) "SYS",
(ub4) strlen((const char *)"SYS"), (const text *) "XMLTYPE",
(ub4) strlen((const char *)"XMLTYPE"), (CONST text *) 0,
(ub4) 0, OCI_DURATION_SESSION, OCI_TYPEGET_HEADER,
(OCIType **) &xmltdo);
if (status == OCI_SUCCESS)
{
status = exec_bind_xml(svchp, errhp, stmthp, (void *)doc,
xmltdo, ins_stmt);
}
if (status == OCI_SUCCESS)
printf ("Insert successful\n");
else
printf ("Insert failed\n");
/* Free XML instances */
if (doc)
XmlFreeDocument((xmlctx *)xctx, (xmldocnode *)doc);
/* Free XML CTX */
OCIXmlDbFreeXmlCtx(xctx);
free_oci();
}
親トピック: Oracle XML DBへのXMLコンテンツのロード
3.5.4 小規模なXML文書を含む大規模なXMLファイルのロード
小規模なXML文書のコレクションで構成された大規模なXMLファイルをロードするときは、Simple API for XML(SAX)の解析機能を使用してファイルを一連の小規模な文書に分割してから文書を挿入すると、効率的にロードできます。
SAXは、XML Parserがイベント・ベース・アプリケーション用に提供するXML標準インタフェースです。SAXを使用して、ノードのコレクションから各文書を作成することによって、30MB以上の大規模なXMLファイルからデータベース表をロードできます。XMLファイルは、バルク・ロードすることもできます。
関連項目:
-
SAXプロジェクト: SAXの詳細
-
OTNのOracle XML DB: SAXを使用して大きなファイルをロードするアプリケーションの例
親トピック: Oracle XML DBへのXMLコンテンツのロード
3.5.5 SQL*Loaderを使用した大規模なXMLファイルのロード
SQL*Loaderを使用すると、大量のXMLデータをOracle Databaseにロードできます。
SQL*Loaderは、従来型パスまたはダイレクト・パスのいずれかのモードでロードを実行します。表3-1に、2つのモードの比較を示します。
表3-1 SQL*Loaderの従来型パスおよびダイレクト・パスによるロード・モード
従来型パスによるロード・モード | ダイレクト・パスによるロード・モード |
---|---|
SQLを使用してデータをOracle Databaseにロードします。これはデフォルトのモードです。 |
SQLをバイパスして、データを直接Oracle Databaseにロードします。 |
メリット: SQLセマンティクスに従います。たとえば、トリガーが起動され、制約がチェックされます。 |
メリット: 従来のロード・モードより高速にデータをロードできます。 |
デメリット: ダイレクト・ロード・モードよりもデータのロードが遅くなります。 |
デメリット: SQLセマンティクスに従いません。たとえば、トリガーは起動されず、制約もチェックされません。 |
SQL*Loaderのダイレクト・パス・モードでLOBをロードすると、多くのメモリーを使用できます。メッセージSQL*Loader 700 (out of memory)
が表示された場合は、オペレーティング・システムおよびプロセス・メモリーで処理できる行より多くの行が各ロード・コールに含まれている可能性があります。回避策: ROWS
オプションを使用して、各データ保存で読み取られる行数を少なくします。
関連トピック
親トピック: Oracle XML DBへのXMLコンテンツのロード
3.5.6 DBMS_XDB_REPOSを使用したリポジトリへのXML文書のロード
PL/SQLパッケージDBMS_XDB_REPOS
を使用すると、XML文書をOracle XML DBリポジトリにロードできます。表ベースではなく、パスベースの方法でリポジトリの文書(リソース)にアクセスできます。
指定のパスのリポジトリにXML文書をロードするには、PL/SQL関数DBMS_XDB_REPOS.createResource
を使用します。例3-16に、これを示します。
Oracle XML DBを構成して使用するための多くの操作は、1つ以上のXML文書の処理に基づいています。たとえば、XML Schemaの登録や、XSL変換の実行などです。これらのXML文書をOracle Databaseで使用可能にする最も簡単な方法は、そのXML文書をOracle XML DBリポジトリにロードすることです。
例3-16 CREATERESOURCEを使用したリポジトリへのXMLコンテンツの挿入
DECLARE
res BOOLEAN;
BEGIN
res := DBMS_XDB_REPOS.createResource('/home/QUINE/purchaseOrder.xml',
bfilename('XMLDIR', 'purchaseOrder.xml'),
nls_charset_id('AL32UTF8'));
END;/
親トピック: Oracle XML DBへのXMLコンテンツのロード
3.5.7 プロトコルを使用したリポジトリへの文書のロード
文書は、XML文書を含め、一般的なプロトコルを使用して、ローカル・ファイル・システムからOracle XML DBリポジトリにロードできます。
Oracle XML DBリポジトリには、XML Schemaに基づくXML文書もXML Schemaに基づかないXML文書も格納できます。HTMLファイル、画像ファイルおよびMicrosoft Word文書などのXMLデータでないコンテンツも格納できます。
Windows ExplorerなどWebDAVをサポートするツールからWebDAVプロトコルなどのプロトコルを使用して、ローカル・ファイル・システムからOracle XML DBリポジトリにXML文書をロードできます。図3-1に、SCOTT
フォルダのコンテンツをローカル・ハード・ドライブからOracle XML DBリポジトリ内のフォルダpoSource
にコピーする簡単なドラッグ・アンド・ドロップ操作を示します。
コピーされたフォルダには、XML Schema文書、HTMLページおよびいくつかのXSLTスタイルシートが含まれていることがあります。
親トピック: Oracle XML DBへのXMLコンテンツのロード
3.6 Oracle XML DBに格納されたXMLコンテンツの問合せ
Oracle XML DBのXMLコンテンツを問い合せて取得する方法は多数あります。
注意:
効率的な問合せパフォーマンスを実現するために、通常、索引を作成する必要があります。XMLデータの索引付けの詳細は、XMLTypeデータの索引を参照してください。
- 例で使用されているXML文書PurchaseOrder
XML Schemaは、例で使用されている発注書を定義します。 - 疑似列OBJECT_VALUEを使用したXML文書のコンテンツの取出し
疑似列OBJECT_VALUE
は、オブジェクト表の値の別名として使用できます。 - XMLQUERYを使用したXML文書のフラグメントまたはノードへのアクセス
SQL/XML関数XMLQuery
を使用すると、XQuery式と一致するノードを抽出できます。結果は、XMLType
のインスタンスとして戻されます。 - XMLCASTおよびXMLQUERYを使用したテキスト・ノードおよび属性値へのアクセス
テキスト・ノードおよび属性値には、SQL/XML標準関数XMLQuery
およびXMLCast
を使用してアクセスできます。 - XMLEXISTS、XMLCASTおよびXMLQUERYを使用したXML文書の検索
SQL/XML標準関数XMLExists
、XMLCast
およびXMLQuery
をSQLWHERE
句で使用すると、問合せ結果を制限できます。 - XMLTABLEを使用したXMLTypeフラグメントでのSQL操作の実行
SQL/XML関数XMLTable
を使用すると、XQuery式と一致する一連のノードに対してSQL操作を実行できます。
親トピック: Oracle XML DBの使用方法の概要
3.6.1 例で使用されているXML文書PurchaseOrder
XML Schemaは、例で使用されている発注書を定義します。
ここに示す例は、例3-17のXML文書PurchaseOrder
に基づいています。
例3-17 XMLインスタンス・ドキュメントPurchaseOrder
<PurchaseOrder
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation=
"http://localhost:8080/source/schemas/poSource/xsd/purchaseOrder.xsd">
<Reference>SBELL-2002100912333601PDT</Reference>
<Actions>
<Action>
<User>SVOLLMAN</User>
</Action>
</Actions>
<Reject/>
<Requestor>Sarah J. Bell</Requestor>
<User>SBELL</User>
<CostCenter>S30</CostCenter>
<ShippingInstructions>
<name>Sarah J. Bell</name>
<address>400 Oracle Parkway
Redwood Shores
CA
94065
USA</address>
<telephone>650 506 7400</telephone>
</ShippingInstructions>
<SpecialInstructions>Air Mail</SpecialInstructions>
<LineItems>
<LineItem ItemNumber="1">
<Description>A Night to Remember</Description>
<Part Id="715515009058" UnitPrice="39.95" Quantity="2"/>
</LineItem>
<LineItem ItemNumber="2">
<Description>The Unbearable Lightness Of Being</Description>
<Part Id="37429140222" UnitPrice="29.95" Quantity="2"/>
</LineItem>
<LineItem ItemNumber="3">
<Description>Sisters</Description>
<Part Id="715515011020" UnitPrice="29.95" Quantity="4"/>
</LineItem>
</LineItems>
</PurchaseOrder>
3.6.2 疑似列OBJECT_VALUEを使用したXML文書のコンテンツの取出し
疑似列OBJECT_VALUE
は、オブジェクト表の値の別名として使用できます。
XMLType
の単一列からなるXMLType
表の場合、XML文書全体が取り出されます。(OBJECT_VALUE
は、Oracle Database 10g リリース1より前のリリースで使用されていたvalue(x)
およびSYS_NC_ROWINFO$
別名に置き換わるものです。)
例3-18では、文書全体が改行なしで正しく出力されるように、SQL*Plus設定のPAGESIZE
およびLONG
を使用しています。(読みやすいように、フォーマット出力で示しています。)
例3-18 OBJECT_VALUEを使用したXML文書全体の取出し
SELECT OBJECT_VALUE FROM purchaseorder;
OBJECT_VALUE
-----------------------------------------------------------------------
<PurchaseOrder xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="http://localhost:8080/source/schemas
/poSource/xsd/purchaseOrder.xsd">
<Reference>SBELL-2002100912333601PDT</Reference>
<Actions>
<Action>
<User>SVOLLMAN</User>
</Action>
</Actions>
<Reject/>
<Requestor>Sarah J. Bell</Requestor>
<User>SBELL</User>
<CostCenter>S30</CostCenter>
<ShippingInstructions>
<name>Sarah J. Bell</name>
<address>400 Oracle Parkway
Redwood Shores
CA
94065
USA</address>
<telephone>650 506 7400</telephone>
</ShippingInstructions>
<SpecialInstructions>Air Mail</SpecialInstructions>
<LineItems>
<LineItem ItemNumber="1">
<Description>A Night to Remember</Description>
<Part Id="715515009058" UnitPrice="39.95" Quantity="2"/>
</LineItem>
<LineItem ItemNumber="2">
<Description>The Unbearable Lightness Of Being</Description>
<Part Id="37429140222" UnitPrice="29.95" Quantity="2"/>
</LineItem>
<LineItem ItemNumber="3">
<Description>Sisters</Description>
<Part Id="715515011020" UnitPrice="29.95" Quantity="4"/>
</LineItem>
</LineItems>
</PurchaseOrder>
1 row selected.
3.6.3 XMLQUERYを使用したXML文書のフラグメントまたはノードへのアクセス
SQL/XML関数XMLQuery
を使用すると、XQuery式と一致するノードを抽出できます。結果は、XMLType
のインスタンスとして戻されます。
例3-19に、複数の問合せの例を示します。
例3-19 XMLQUERYを使用したXMLフラグメントへのアクセス
次の問合せは、XPath式と一致するReference
要素を含むXMLType
インスタンスを戻します。
SELECT XMLQuery('/PurchaseOrder/Reference' PASSING OBJECT_VALUE RETURNING CONTENT)
FROM purchaseorder;
XMLQUERY('/PURCHASEORDER/REFERENCE'PASSINGOBJECT_
-------------------------------------------------
<Reference>SBELL-2002100912333601PDT</Reference>
1 row selected.
次の問合せは、LineItem
コレクション内の最初のLineItems
要素を含むXMLType
インスタンスを戻します。
SELECT XMLQuery('/PurchaseOrder/LineItems/LineItem[1]'
PASSING OBJECT_VALUE RETURNING CONTENT)
FROM purchaseorder;
XMLQUERY('/PURCHASEORDER/LINEITEMS/LINEITEM[1]'PASSINGOBJECT_
-------------------------------------------------------------
<LineItem ItemNumber="1">
<Description>A Night to Remember</Description>
<Part Id="715515009058" UnitPrice="39.95" Quantity="2"/>
</LineItem>
1 row selected.
次の問合せは、XPath式と一致する3つのDescription
要素を含むXMLType
インスタンスを戻します。これらの要素は、単一のXMLType
インスタンス内のノードとして戻されます。XMLType
インスタンスはXMLフラグメントなので、単一のルート・ノードを持ちません。
SELECT XMLQuery('/PurchaseOrder/LineItems/LineItem/Description'
PASSING OBJECT_VALUE RETURNING CONTENT)
FROM purchaseorder;
XMLQUERY('/PURCHASEORDER/LINEITEMS/LINEITEM/DESCRIPTION'PASSINGOBJECT_
----------------------------------------------------------------------
<Description>A Night to Remember</Description>
<Description>The Unbearable Lightness Of Being</Description>
<Description>Sisters</Description>
1 row selected.
3.6.4 XMLCASTおよびXMLQUERYを使用したテキスト・ノードおよび属性値へのアクセス
テキスト・ノードおよび属性値には、SQL/XML標準関数XMLQuery
およびXMLCast
を使用してアクセスできます。
このためには、XMLQuery
に渡されるXQuery式は、文書内の単一のテキスト・ノードまたは属性値(リーフ・ノード)を一意に識別する必要があります。例3-20に、複数の問合せを使用する例を示します。
関連項目:
SQL/XML関数XMLQuery
およびXMLCast
の詳細は、XQueryとOracle XML DBを参照してください。
例3-20 XMLCASTおよびXMLQueryを使用したテキスト・ノード値へのアクセス
次の問合せは、対象のXPath式と一致するReference
要素に関連付けられたテキスト・ノードの値を戻します。値は、VARCHAR2
値として戻されます。
SELECT XMLCast(XMLQuery('$p/PurchaseOrder/Reference/text()'
PASSING OBJECT_VALUE AS "p" RETURNING CONTENT)
AS VARCHAR2(30))
FROM purchaseorder;
XMLCAST(XMLQUERY('$P/PURCHASEO
------------------------------
SBELL-2002100912333601PDT
1 row selected.
次の問合せは、LineItem
要素に含まれるDescription
要素に関連付けられたテキスト・ノードの値を戻します。特定のLineItem
要素は、そのId
属性値によって指定されます。LineItem
要素を識別する述語は、[Part/@Id="715515011020"]
です。アットマーク(@
)は、Id
が要素でなく属性であることを指定します。値は、VARCHAR2
値として戻されます。
SELECT XMLCast(
XMLQuery('$p/PurchaseOrder/LineItems/LineItem[Part/@Id="715515011020"]/Description/text()'
PASSING OBJECT_VALUE AS "p" RETURNING CONTENT)
AS VARCHAR2(30))
FROM purchaseorder;
XMLCAST(XMLQUERY('$P/PURCHASEO
------------------------------
Sisters
1 row selected.
次の問合せは、最初のLineItem
要素に含まれるDescription
要素に関連付けられたテキスト・ノードの値を戻します。最初のLineItem
要素は、位置述語[1]
で示されます。
SELECT XMLCast(XMLQuery('$p/PurchaseOrder/LineItems/LineItem[1]/Description'
PASSING OBJECT_VALUE AS "p" RETURNING CONTENT)
AS VARCHAR2(4000))
FROM purchaseorder;
XMLCAST(XMLQUERY('$P/PURCHASEORDER/LINEITEMS/LINEITEM[1]/DESCRIPTION'PASSINGOBJECT_VALUEAS"P"
---------------------------------------------------------------------------------------------
A Night to Remember
1 row selected.
3.6.5 XMLEXISTS、XMLCASTおよびXMLQUERYを使用したXML文書の検索
SQL/XML標準関数XMLExists
、XMLCast
およびXMLQuery
をSQL WHERE
句で使用すると、問合せ結果を制限できます。
SQL/XML標準関数XMLExists
は、指定された文書にW3CのXPath式と一致するノードが含まれているかどうかを評価します。これは、関数に指定されたXPath式によって指定されたノードが文書に含まれている場合はブール値のtrue
を、そうでない場合はfalse
の値を戻します。XPath式には述語を含めることができるため、XMLExists
は、指定されたノードが文書内に存在するかどうか、および指定された値を持つノードが文書内に存在するかどうかを判断できます。
同様に、関数XMLCast
およびXMLQuery
を使用すると、問合せ結果を一部のプロパティを満たす文書に制限できます。例3-21に、XMLExists
、XMLCast
およびXMLQuery
を使用して文書を検索する方法を示します。
例3-22では、XML文書内のノードの値と別のリレーショナル表のデータに基づいて結合を実行しています。
関連項目:
SQL/XML関数XMLQuery
、XMLExists
およびXMLCast
の詳細は、XQueryとOracle XML DBを参照してください。
例3-21 XMLExists、XMLCastおよびXMLQueryを使用したXMLコンテンツの検索
次の問合せでは、XMLExists
を使用して、ルート要素PurchaseOrder
の子であるReference
という要素がXML文書に含まれているかどうかを確認します。
SELECT count(*) FROM purchaseorder WHERE XMLExists('$p/PurchaseOrder/Reference' PASSING OBJECT_VALUE AS "p"); COUNT(*) ---------- 132 1 row selected.
次の問合せでは、Reference
要素に関連付けられたテキスト・ノードの値がSBELL-2002100912333601PDT
であるかどうかを確認します。
SELECT count(*) FROM purchaseorder
WHERE XMLExists('$p/PurchaseOrder[Reference="SBELL-2002100912333601PDT"]'
PASSING OBJECT_VALUE AS "p");
COUNT(*)
----------
1
1 row selected.
この問合せでは、XML文書にルート要素PurchaseOrder
が含まれているかどうかを確認します。このルート要素に含まれるLineItems
要素にはLineItem
要素が含まれ、さらにこの要素にはId
属性を持つPart
要素が含まれている必要があります。
SELECT count(*) FROM purchaseorder
WHERE XMLExists('$p/PurchaseOrder/LineItems/LineItem/Part/@Id'
PASSING OBJECT_VALUE AS "p");
COUNT(*)
----------
132
1 row selected.
次の問合せでは、XML文書にルート要素PurchaseOrder
が含まれているかどうかを確認します。このルート要素に含まれるLineItems
要素にはLineItem
要素が含まれ、さらにこの要素にはId
属性値が715515009058
のPart
要素が含まれている必要があります。
SELECT count(*) FROM purchaseorder
WHERE XMLExists('$p/PurchaseOrder/LineItems/LineItem/Part[@Id="715515009058"]'
PASSING OBJECT_VALUE AS "p");
COUNT(*)
----------
21
次の問合せでは、XML文書にルート要素PurchaseOrder
が含まれているかどうかを確認します。このルート要素にはLineItem
要素が含まれ、さらにこの要素の3番目のLineItem
要素にはId
属性値が715515009058
のPart
要素が含まれます。
SELECT count(*) FROM purchaseorder
WHERE XMLExists(
'$p/PurchaseOrder/LineItems/LineItem[3]/Part[@Id="715515009058"]'
PASSING OBJECT_VALUE AS "p");
COUNT(*)
----------
1
1 row selected.
次の問合せは、User
要素に関連付けられたテキスト・ノードが文字S
で始まる行のみをSELECT
文の結果として戻します。XQueryでは、LIKE
を使用した問合せをサポートしていません。
SELECT XMLCast(XMLQuery('$p/PurchaseOrder/Reference' PASSING OBJECT_VALUE AS "p" RETURNING CONTENT) AS VARCHAR2(30)) FROM purchaseorder WHERE XMLCast(XMLQuery('$p/PurchaseOrder/User' PASSING OBJECT_VALUE AS "p" RETURNING CONTENT) AS VARCHAR2(30)) LIKE 'S%'; XMLCAST(XMLQUERY('$P/PURCHASEORDER ---------------------------------- SBELL-20021009123336231PDT SBELL-20021009123336331PDT SKING-20021009123336321PDT ... 36 rows selected.
次の問合せは、XMLExists
を使用して、User
要素のテキスト・ノードに値SBELL
が含まれる行のみをSELECT
文の結果として戻します。
SELECT XMLCast(XMLQuery('$p/PurchaseOrder/Reference' PASSING OBJECT_VALUE AS "p"
RETURNING CONTENT)
AS VARCHAR2(30)) "Reference"
FROM purchaseorder
WHERE XMLExists('$p/PurchaseOrder[User="SBELL"]' PASSING OBJECT_VALUE AS "p");
Reference
------------------------------
SBELL-20021009123336231PDT
SBELL-20021009123336331PDT
SBELL-20021009123337353PDT
SBELL-20021009123338304PDT
SBELL-20021009123338505PDT
SBELL-20021009123335771PDT
SBELL-20021009123335280PDT
SBELL-2002100912333763PDT
SBELL-2002100912333601PDT
SBELL-20021009123336362PDT
SBELL-20021009123336532PDT
SBELL-20021009123338204PDT
SBELL-20021009123337673PDT
13 rows selected.
次の例では、SQL/XML関数XMLQuery
およびXMLExists
を使用して、最初のLineItem
要素にId
715515009058
の注文が含まれるPurchaseOrder
要素についてReference
要素を検索します。関数XMLExists
をWHERE
句で使用して、選択する行を決定し、XMLQuery
をSELECT
リストで使用して、選択された文書のどの部分を結果に表示するかを制御します。
SELECT XMLCast(XMLQuery('$p/PurchaseOrder/Reference' PASSING OBJECT_VALUE AS "p" RETURNING CONTENT) AS VARCHAR2(30)) "Reference" FROM purchaseorder WHERE XMLExists('$p/PurchaseOrder/LineItems/LineItem[1]/Part[@Id="715515009058"]' PASSING OBJECT_VALUE AS "p"); Reference ------------------------- SBELL-2002100912333601PDT 1 row selected.
例3-22 XMLType表とリレーショナル表のデータの結合
SELECT XMLCast(XMLQuery('$p/PurchaseOrder/Reference' PASSING OBJECT_VALUE AS "p" RETURNING CONTENT) AS VARCHAR2(30)) FROM purchaseorder p, hr.employees e WHERE XMLCast(XMLQuery('$p/PurchaseOrder/User' PASSING OBJECT_VALUE AS "p" RETURNING CONTENT) AS VARCHAR2(30)) = e.email AND e.employee_id = 100; XMLCAST(XMLQUERY('$P/PURCHASEOREDER ----------------------------------- SKING-20021009123336321PDT SKING-20021009123337153PDT SKING-20021009123335560PDT SKING-20021009123336952PDT SKING-20021009123336622PDT SKING-20021009123336822PDT SKING-20021009123336131PDT SKING-20021009123336392PDT SKING-20021009123337974PDT SKING-20021009123338294PDT SKING-20021009123337703PDT SKING-20021009123337383PDT SKING-20021009123337503PDT 13 rows selected.
3.6.6 XMLTABLEを使用したXMLTypeフラグメントでのSQL操作の実行
SQL/XML関数XMLTable
を使用すると、XQuery式と一致する一連のノードに対してSQL操作を実行できます。
例3-19は、XPath式と一致する1つ以上のノードを含むXMLType
インスタンスを戻す方法を示しています。指定されたXPath式と一致するノードが文書に複数含まれている場合、このような問合せでは、一致するすべてのノードが含まれるXMLフラグメントを戻します。XML文書と異なり、XMLフラグメントには、ルート要素である単一の要素はありません。
このような結果は、次の場合に一般的です。
-
コレクションに含まれている一連の要素を取り出す場合。この場合、フラグメント内のすべてのノードは同じタイプです(例3-23を参照)。
-
対象のXPath式がワイルドカードで終わる場合。この場合、フラグメント内のノードは異なるタイプになることがあります(例3-25を参照)。
SQL/XML関数XMLTable
を使用すると、XMLType
インスタンスに含まれているXMLフラグメントを分割し、コレクション要素データを新しい仮想表に挿入することができ、その後、SQLを結合式などで使用して問い合せることができます。特に、XMLフラグメントを仮想表に変換することにより、複数のノードを戻すXMLQuery
式の評価の結果を処理しやすくなります。
関連項目:
SQL/XML関数XMLTable
の詳細は、XQueryとOracle XML DBを参照してください。
例3-23に、PurchaseOrder
文書のDescription
要素ごとにテキスト・ノードにアクセスする方法を示します。例3-19の単一のXMLフラグメント出力を複数のテキスト・ノードに分割します。
例3-24では、コレクション内の要素数をカウントします。また、ORDER BY
やGROUP BY
などのSQLキーワードをSQL/XML関数XMLTable
によって作成された仮想表データに適用する方法も示しています。
例3-25では、SQL/XML関数XMLTable
を使用して、指定された要素の子要素の数をカウントする方法を示します。XMLTable
に渡されるXPath式には、PurchaseOrder
要素の直接の子孫である全要素と一致するワイルド・カード(*
)が含まれます。XMLTable
で作成された仮想表の各行には、XPath式と一致するノードが含まれます。仮想表内の行数をカウントすることによって、要素PurchaseOrder
の子要素の数が判明します。
例3-23 XMLTABLEを使用したDescriptionノードへのアクセス
SELECT des.COLUMN_VALUE
FROM purchaseorder p,
XMLTable('/PurchaseOrder/LineItems/LineItem/Description'
PASSING p.OBJECT_VALUE) des
WHERE XMLExists('$p/PurchaseOrder[Reference="SBELL-2002100912333601PDT"]'
PASSING OBJECT_VALUE AS "p");
COLUMN_VALUE
------------
<Description>A Night to Remember</Description>
<Description>The Unbearable Lightness Of Being</Description>
<Description>Sisters</Description>
3 rows selected.
この例では、SQLを使用してテキスト・ノードのコンテンツを処理するために、SQL/XML関数XMLTable
を使用してDescription
ノードのコレクションを仮想表に変換します。この仮想表には3つの行があり、単一のDescription
要素を持つ単一のXMLType
インスタンスが各行に含まれています。
XPath式は、Description
要素をターゲットにしています。PASSING
句では、XPath式を評価するためのコンテキストとしてXMLType
表purchaseorder
のコンテンツ(OBJECT_VALUE
)を使用することを指定しています。
したがって、XMLTable
式はpurchaseorder表に依存します
。これは左側結合です。この相関結合によって、アクセスされるpurchaseorder
行と、XMLTable
によってその行から生成される行は、1対多(1:N)の関係であることが保証されます。この相関結合により、purchaseorder
表は、FROMリストのXMLTable
式よりも前に記述する必要があります
。これは、PASSING
句が表の列を参照する場合に一般的な要件です。
仮想表のXMLType
インスタンスにはそれぞれ、Description
要素が1つずつ含まれます。XMLTable
のCOLUMNS
句を使用して、XPath式'Description'
のターゲットのデータを、SQLデータ型VARCHAR2(256)
のdescription
という列に分割できます。この列を定義する'Description'
式は、コンテキストのXPath式'/PurchaseOrder/LineItems/LineItem'に相対的
です。
SELECT des.description FROM purchaseorder p, XMLTable('/PurchaseOrder/LineItems/LineItem' PASSING p.OBJECT_VALUE COLUMNS description VARCHAR2(256) PATH 'Description') des WHERE XMLExists('$p/PurchaseOrder[Reference="SBELL-2002100912333601PDT"]' PASSING OBJECT_VALUE AS "p"); DESCRIPTION --------------------------------- A Night to Remember The Unbearable Lightness Of Being Sisters 3 rows selected.
COLUMNS
句を使用すると、正確なSQLデータ型を指定できるため、静的型チェックがさらに便利になります。この例では、単一の列(description
)のみを使用します。XMLType
表に複数レベルで含まれているデータをリレーショナル・ビューの個別の行として公開するには、分割してリレーショナル列に格納する各文書レベルにXMLTable
を適用します。この例は、例9-2を参照してください。
例3-24 XMLTABLEを使用したコレクション内の要素数のカウント
SELECT reference, count(*) FROM purchaseorder, XMLTable('/PurchaseOrder' PASSING OBJECT_VALUE COLUMNS reference VARCHAR2(32) PATH 'Reference', lineitem XMLType PATH 'LineItems/LineItem'), XMLTable('LineItem' PASSING lineitem) WHERE XMLExists('$p/PurchaseOrder[User="SBELL"]' PASSING OBJECT_VALUE AS "p") GROUP BY reference ORDER BY reference; REFERENCE COUNT(*) -------------------------- -------- SBELL-20021009123335280PDT 20 SBELL-20021009123335771PDT 21 SBELL-2002100912333601PDT 3 SBELL-20021009123336231PDT 25 SBELL-20021009123336331PDT 10 SBELL-20021009123336362PDT 15 SBELL-20021009123336532PDT 14 SBELL-20021009123337353PDT 10 SBELL-2002100912333763PDT 21 SBELL-20021009123337673PDT 10 SBELL-20021009123338204PDT 14 SBELL-20021009123338304PDT 24 SBELL-20021009123338505PDT 20 13 rows selected.
この例の問合せでは、SQL/XML関数XMLExists
へのXPath式と一致する一連のXML文書が検索されます。これにより、次の2つの列を含む仮想表が生成されます。
-
reference
: この列には、選択された各文書のReference
ノードが含まれます。 -
lineitem
: この列には、選択された各文書の一連のLineItem
ノードが含まれます。
文書ごとにLineItem
ノードの数がカウントされます。相関結合によって、GROUP BY
はLineItem
要素が属するPurchaseOrder
要素を正しく判別できます。
例3-25 XMLTABLEを使用した要素内の子要素数のカウント
SELECT count(*)
FROM purchaseorder p, XMLTable('/PurchaseOrder/*' PASSING p.OBJECT_VALUE)
WHERE XMLExists('$p/PurchaseOrder[Reference="SBELL-2002100912333601PDT"]'
PASSING OBJECT_VALUE AS "p");
COUNT(*)
----------
9
1 row selected.
3.7 Oracle XML DBに格納されたXMLコンテンツの更新
XMLコンテンツを更新する場合は、文書のコンテンツ全体または文書の特定部分のみを置換できます。
XML文書を部分的に更新する機能は非常に強力で、特に大きな文書に小さな変更を行う場合に、更新の実行に必要なネットワーク・トラフィックとディスクの入出力を大幅に削減できます。
文書に対する複数の変更を1回の操作で実行できます。どちらの場合も、XQuery式を使用して更新するノードを特定し、そのノードに新しい値を指定します。
例3-26では、要素User
に関連付けられたテキスト・ノードを更新します。
例3-27では、XML文書内の要素全体を置換します。XQuery式によって要素が参照され、置換値はXMLType
オブジェクトとして渡されます。
文書に対する複数の変更を1つの文で実行できます。例3-28では、要素CostCenter
およびSpecialInstructions
に属するテキスト・ノードの値を1つのSQL UPDATE
文で変更します。
例3-26 テキスト・ノードの更新
SELECT XMLCast(XMLQuery('$p/PurchaseOrder/User' PASSING OBJECT_VALUE AS "p"
RETURNING CONTENT)
AS VARCHAR2(60))
FROM purchaseorder
WHERE XMLExists('$p/PurchaseOrder[Reference="SBELL-2002100912333601PDT"]'
PASSING OBJECT_VALUE AS "p");
XMLCAST(XMLQUERY('$P/PURCHAS
----------------------------
SBELL
1 row selected.
UPDATE purchaseorder
SET OBJECT_VALUE =
XMLQuery('copy $i := $p1 modify
(for $j in $i/PurchaseOrder/User
return replace value of node $j with $p2)
return $i'
PASSING OBJECT_VALUE AS "p1", 'SKING' AS "p2" RETURNING CONTENT)
WHERE XMLExists('$p/PurchaseOrder[Reference="SBELL-2002100912333601PDT"]'
PASSING OBJECT_VALUE AS "p");
1 row updated.
SELECT XMLCast(XMLQuery('$p/PurchaseOrder/User' PASSING OBJECT_VALUE AS "p"
RETURNING CONTENT)
AS VARCHAR2(60))
FROM purchaseorder
WHERE XMLExists('$p/PurchaseOrder[Reference="SBELL-2002100912333601PDT"]'
PASSING OBJECT_VALUE AS "p");
XMLCAST(XMLQUERY('$P/PURCHAS
----------------------------
SKING
1 row selected.
例3-27 XQuery Updateを使用した要素全体の置換
SELECT XMLQuery('$p/PurchaseOrder/LineItems/LineItem[1]'
PASSING OBJECT_VALUE AS "p" RETURNING CONTENT)
FROM purchaseorder
WHERE XMLExists('$p/PurchaseOrder[Reference="SBELL-2002100912333601PDT"]'
PASSING OBJECT_VALUE AS "p");
XMLQUERY('$P/PURCHAS
--------------------
<LineItem ItemNumber="1">
<Description>A Night to Remember</Description>
<Part Id="715515009058" UnitPrice="39.95" Quantity="2"/>
</LineItem>
1 row selected.
UPDATE purchaseorder
SET OBJECT_VALUE =
XMLQuery('copy $i := $p1 modify
(for $j in $i/PurchaseOrder/LineItems/LineItem[1]
return replace node $j with $p2)
return $i'
PASSING OBJECT_VALUE AS "p1",
XMLType('<LineItem ItemNumber="1">
<Description>The Lady Vanishes</Description>
<Part Id="37429122129" UnitPrice="39.95"
Quantity="1"/>
</LineItem>') AS "p2"
RETURNING CONTENT)
WHERE XMLExists('$p/PurchaseOrder[Reference="SBELL-2002100912333601PDT"]'
PASSING OBJECT_VALUE AS "p");
1 row updated.
SELECT XMLQuery('$p/PurchaseOrder/LineItems/LineItem[1]'
PASSING OBJECT_VALUE AS "p" RETURNING CONTENT)
FROM purchaseorder
WHERE XMLExists('$p/PurchaseOrder[Reference="SBELL-2002100912333601PDT"]'
PASSING OBJECT_VALUE AS "p");
XMLQUERY('$P/PURCHAS
--------------------
<LineItem ItemNumber="1">
<Description>The Lady Vanishes</Description>
<Part Id="37429122129" UnitPrice="39.95" Quantity="1"/>
</LineItem>
1 row selected.
例3-28 XQuery Updateを使用したテキスト・ノード値の変更
SELECT XMLCast(XMLQuery('$p/PurchaseOrder/CostCenter'
PASSING OBJECT_VALUE AS "p" RETURNING CONTENT)
AS VARCHAR2(4)) "Cost Center",
XMLCast(XMLQuery('$p/PurchaseOrder/SpecialInstructions'
PASSING OBJECT_VALUE AS "p" RETURNING CONTENT)
AS VARCHAR2(2048)) "Instructions"
FROM purchaseorder
WHERE XMLExists('$p/PurchaseOrder[Reference="SBELL-2002100912333601PDT"]'
PASSING OBJECT_VALUE AS "p");
Cost Center Instructions
------------ ------------
S30 Air Mail
1 row selected.
UPDATE purchaseorder
SET OBJECT_VALUE =
XMLQuery('copy $i := $p1 modify
((for $j in $i/PurchaseOrder/CostCenter
return replace value of node $j with $p2),
(for $j in $i/PurchaseOrder/SpecialInstructions
return replace value of node $j with $p3))
return $i'
PASSING OBJECT_VALUE AS "p1",
'B40' AS "p2",
'Priority Overnight Service' AS "p3"
RETURNING CONTENT)
WHERE XMLExists('$p/PurchaseOrder[Reference="SBELL-2002100912333601PDT"]'
PASSING OBJECT_VALUE AS "p");
1 row updated.
SELECT XMLCast(XMLQuery('$p/PurchaseOrder/CostCenter'
PASSING OBJECT_VALUE AS "p" RETURNING CONTENT)
AS VARCHAR2(4)) "Cost Center",
XMLCast(XMLQuery('$p/PurchaseOrder/SpecialInstructions'
PASSING OBJECT_VALUE AS "p" RETURNING CONTENT)
AS VARCHAR2(2048)) "Instructions"
FROM purchaseorder
WHERE XMLExists('$p/PurchaseOrder[Reference="SBELL-2002100912333601PDT"]'
PASSING OBJECT_VALUE AS "p");
Cost Center Instructions
------------ --------------------------
B40 Priority Overnight Service
1 row selected.
親トピック: Oracle XML DBの使用方法の概要
3.8 リレーショナル・データからのXMLデータの生成
Oracle XML DBを使用して、リレーショナル・データからXMLデータを生成できます。
- SQL/XML関数を使用した、リレーショナル・データからのXMLデータの生成
標準のSQL/XML関数を使用すると、XML文書を1つ以上生成できます。 - DBURITYPEを使用した、リレーショナル・データからのXMLデータの生成
SQL関数DBURIType
を使用して、リレーショナル・データからXMLデータを生成できます。
親トピック: Oracle XML DBの使用方法の概要
3.8.1 SQL/XML関数を使用した、リレーショナル・データからのXMLデータの生成
標準のSQL/XML関数を使用すると、XML文書を1つ以上生成できます。
SQL/XML関数XMLQuery
は、これを行うための最も一般的な方法です。この操作に使用できるSQL/XML関数には、他に次のものがあります。
-
XMLElement
は、要素を作成します。 -
XMLAttributes
は、属性を要素に追加します。 -
XMLForest
は、要素のフォレストを作成します。 -
XMLAgg
は、要素のコレクションから単一の要素を作成します。
例3-29の問合せでは、これらの関数を使用して、表departments
、locations
、countries
、employees
およびjobs
の情報を含むXML文書を生成します。
この問合せは、departments
表の行ごとに要素Department
を生成します。
-
各
Department
要素には、属性DepartmentID
が含まれます。DepartmentID
の値はdepartment_ed
列から生成されます。このDepartment
要素には、サブ要素のName
、Location
およびEmployeeList
も含まれます。 -
Name
要素に関連付けられたテキスト・ノードは、departments
表のname
列から生成されます。 -
Location
要素には、子要素Address
、City
、State
、Zip
およびCountry
が含まれます。これらの要素は、locations
表およびcountries
表の列からフォレスト、つまり名前付き要素を作成することで構成されます。列内の値は、名前付き要素に対するテキスト・ノードになります。 -
EmployeeList
要素には、Employee
要素の集計が含まれます。EmployeeList
要素のコンテンツは、現在の部門に対応するemployees
表の一連の行を戻す副問合せによって作成されます。各Employee
要素には、従業員に関する情報が含まれます。各Employee
要素のコンテンツおよび属性は、表employees
およびjobs
から取得されます。
SQL/XML関数で生成される出力は、通常はフォーマット出力ではありません。ただし、関数XMLSerialize
は例外で、XMLSerialize
を使用してフォーマット出力します。このため、他のSQL/XML関数で必要な出力を生成するときに、(1)完全なDOMが作成されるのを回避し、(2)生成される文書のサイズを縮小できます。ほとんどのアプリケーションでは、このように大半のSQL/XML関数でフォーマット出力が生成されなくても問題ありません。ただし、生成された出力を手動で検証することは困難になります。
また、SQL/XML生成関数を使用して構築されるXMLType
ビューを作成および問合せすることもできます。例3-30および例3-31に、これを示します。このようなXMLType
ビューには、リレーショナル・データをXMLコンテンツとして永続的に保持する効果があります。また、XMLType
ビューの行は、Oracle XML DBリポジトリに文書として永続的に保持できます。
例3-31では、SQL/XML関数XMLExists
に渡されるXPath式によって、問合せ結果セットは、Executive
部門の情報が含まれたノードに制限されます。結果は、わかりやすくするためフォーマット出力しています。
注意:
XMLType
ビューで操作するXML式でのXPathリライトは、XPath式で参照するノードが、SQL関数XMLAggを使用して作成された要素の子孫でない
場合にのみサポートされます。
例3-29 SQL/XML関数を使用したXMLデータの生成
SELECT XMLElement(
"Department",
XMLAttributes(d.Department_id AS "DepartmentId"),
XMLForest(d.department_name AS "Name"),
XMLElement(
"Location",
XMLForest(street_address AS "Address",
city AS "City",
state_province AS "State",
postal_code AS "Zip",
country_name AS "Country")),
XMLElement(
"EmployeeList",
(SELECT XMLAgg(
XMLElement(
"Employee",
XMLAttributes(e.employee_id AS "employeeNumber"),
XMLForest(
e.first_name AS "FirstName",
e.last_name AS "LastName",
e.email AS "EmailAddress",
e.phone_number AS "PHONE_NUMBER",
e.hire_date AS "StartDate",
j.job_title AS "JobTitle",
e.salary AS "Salary",
m.first_name || ' ' || m.last_name AS "Manager"),
XMLElement("Commission", e.commission_pct)))
FROM hr.employees e, hr.employees m, hr.jobs j
WHERE e.department_id = d.department_id
AND j.job_id = e.job_id
AND m.employee_id = e.manager_id)))
AS XML
FROM hr.departments d, hr.countries c, hr.locations l
WHERE department_name = 'Executive'
AND d.location_id = l.location_id
AND l.country_id = c.country_id;
この問合せでは、次のXMLが戻されます。
XML
--------------------------------------------------------------------------------
<Department DepartmentId="90"><Name>Executive</Name><Location><Address>2004
Charade Rd</Address><City>Seattle</City><State>Washingto
n</State><Zip>98199</Zip><Country>United States of
America</Country></Location><EmployeeList><Employee
employeeNumber="101"><FirstNa
me>Neena</FirstName><LastName>Kochhar</LastName><EmailAddress>NKOCHHAR</EmailAdd
ess><PHONE_NUMBER>515.123.4568</PHONE_NUMBER><Start
Date>2005-09-21</StartDate><JobTitle>Administration Vice
President</JobTitle><Salary>17000</Salary><Manager>Steven King</Manager><Com
mission></Commission></Employee><Employee
employeeNumber="102"><FirstName>Lex</FirstName><LastName>De
Haan</LastName><EmailAddress>L
DEHAAN</EmailAddress><PHONE_NUMBER>515.123.4569</PHONE
NUMBER><StartDate>2001-01-13</StartDate><JobTitle>Administration Vice Presiden
t</JobTitle><Salary>17000</Salary><Manager>Steven
King</Manager><Commission></Commission></Employee></EmployeeList></Department>
例3-30 従来のリレーショナル表のXMLTypeビューの作成
CREATE OR REPLACE VIEW department_xml OF XMLType
WITH OBJECT ID (substr(
XMLCast(
XMLQuery('$p/Department/Name'
PASSING OBJECT_VALUE AS "p" RETURNING CONTENT)
AS VARCHAR2(30)),
1,
128))
AS
SELECT XMLElement(
"Department",
XMLAttributes(d.department_id AS "DepartmentId"),
XMLForest(d.department_name AS "Name"),
XMLElement("Location", XMLForest(street_address AS "Address",
city AS "City",
state_province AS "State",
postal_code AS "Zip",
country_name AS "Country")),
XMLElement(
"EmployeeList",
(SELECT XMLAgg(
XMLElement(
"Employee",
XMLAttributes(e.employee_id AS "employeeNumber"),
XMLForest(e.first_name AS "FirstName",
e.last_name AS "LastName",
e.email AS "EmailAddress",
e.phone_number AS "PHONE_NUMBER",
e.hire_date AS "StartDate",
j.job_title AS "JobTitle",
e.salary AS "Salary",
m.first_name || ' ' ||
m.last_name AS "Manager"),
XMLElement("Commission", e.commission_pct)))
FROM hr.employees e, hr.employees m, hr.jobs j
WHERE e.department_id = d.department_id
AND j.job_id = e.job_id
AND m.employee_id = e.manager_id))).extract('/*')
AS XML
FROM hr.departments d, hr.countries c, hr.locations l
WHERE d.location_id = l.location_id
AND l.country_id = c.country_id;
例3-31 XMLTypeビューの問合せ
SELECT OBJECT_VALUE FROM department_xml
WHERE XMLExists('$p/Department[Name="Executive"]' PASSING OBJECT_VALUE AS "p");
OBJECT_VALUE
------------------------------------------------
<Department DepartmentId="90">
<Name>Executive</Name>
<Location>
<Address>2004 Charade Rd</Address>
<City>Seattle</City>
<State>Washington</State>
<Zip>98199</Zip>
<Country>United States of America</Country>
</Location>
<EmployeeList>
<Employee employeeNumber="101">
<FirstName>Neena</FirstName>
<LastName>Kochhar</LastName>
<EmailAddress>NKOCHHAR</EmailAddress>
<PHONE_NUMBER>515.123.4568</PHONE_NUMBER>
<StartDate>2005-09-21</StartDate>
<JobTitle>Administration Vice President</JobTitle>
<Salary>17000</Salary>
<Manager>Steven King</Manager>
<Commission/>
</Employee>
<Employee employeeNumber="102">
<FirstName>Lex</FirstName>
<LastName>De Haan</LastName>
<EmailAddress>LDEHAAN</EmailAddress>
<PHONE_NUMBER>515.123.4569</PHONE_NUMBER>
<StartDate>2001-01-13</StartDate>
<JobTitle>Administration Vice President</JobTitle>
<Salary>17000</Salary>
<Manager>Steven King</Manager>
<Commission/>
</Employee>
</EmployeeList>
</Department>
1 row selected.
次の実行計画の出力に示すとおり、Oracle XML DBには、XMLExists
式のXPath式の引数を、基礎となるリレーショナル表のSELECT
文に正しくリライトする機能があります。
SELECT OBJECT_VALUE FROM department_xml
WHERE XMLExists('$p/Department[Name="Executive"]' PASSING OBJECT_VALUE AS "p");
PLAN_TABLE_OUTPUT
------------------------------------------------------------------------------------------------------------
Plan hash value: 2414180351
------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 80 | 3 (0)| 00:00:01 |
| 1 | SORT AGGREGATE | | 1 | 115 | | |
|* 2 | HASH JOIN | | 10 | 1150 | 7 (15)| 00:00:01 |
|* 3 | HASH JOIN | | 10 | 960 | 5 (20)| 00:00:01 |
| 4 | TABLE ACCESS BY INDEX ROWID BATCHED| EMPLOYEES | 10 | 690 | 2 (0)| 00:00:01 |
|* 5 | INDEX RANGE SCAN | EMP_DEPARTMENT_IX | 10 | | 1 (0)| 00:00:01 |
| 6 | TABLE ACCESS FULL | JOBS | 19 | 513 | 2 (0)| 00:00:01 |
| 7 | TABLE ACCESS FULL | EMPLOYEES | 107 | 2033 | 2 (0)| 00:00:01 |
| 8 | NESTED LOOPS | | 1 | 80 | 3 (0)| 00:00:01 |
| 9 | NESTED LOOPS | | 1 | 68 | 3 (0)| 00:00:01 |
|* 10 | TABLE ACCESS FULL | DEPARTMENTS | 1 | 19 | 2 (0)| 00:00:01 |
| 11 | TABLE ACCESS BY INDEX ROWID | LOCATIONS | 1 | 49 | 1 (0)| 00:00:01 |
|* 12 | INDEX UNIQUE SCAN | LOC_ID_PK | 1 | | 0 (0)| 00:00:01 |
|* 13 | INDEX UNIQUE SCAN | COUNTRY_C_ID_PK | 1 | 12 | 0 (0)| 00:00:01 |
------------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - access("M"."EMPLOYEE_ID"="E"."MANAGER_ID")
3 - access("J"."JOB_ID"="E"."JOB_ID")
5 - access("E"."DEPARTMENT_ID"=:B1)
10 - filter("D"."DEPARTMENT_NAME"='Executive')
12 - access("D"."LOCATION_ID"="L"."LOCATION_ID")
13 - access("L"."COUNTRY_ID"="C"."COUNTRY_ID")
30 rows selected.
親トピック: リレーショナル・データからのXMLデータの生成
3.8.2 DBURITYPEを使用した、リレーショナル・データからのXMLデータの生成
SQL関数DBURIType
を使用して、リレーショナル・データからXMLデータを生成できます。
関数DBURIType
は、指定された表またはビューの1つ以上の行を単一のXML文書として公開します。ルート要素の名前は、表またはビューの名前から導出されます。ルート要素には、一連のROW
要素が含まれます。表またはビュー内の行ごとにROW
要素が1つずつあります。各ROW
要素の子は、表またはビューの列から導出されます。各子要素には、指定された行の列の値を持つテキスト・ノードが含まれます。
例3-32に、SQL関数DBURIType
を使用して、データベース・スキーマHR
の表departments
のコンテンツにアクセスする方法を示します。メソッドgetXML()
を使用して結果の文書をXMLType
インスタンスとして戻します。
例3-33では、XPath述語を使用して、DBURIType
によって生成されるXML文書に含める行を制限する方法を示します。この例のXPath式によって、値が10
のDEPARTMENT_ID
列のみにXML文書が制限されます。
SQL関数DBURIType
を使用すると、リレーショナル表の一部または全部の行を1つ以上のXML文書として簡単に公開できます。関数DBURIType
に渡されるURLを拡張してビューまたは表から単一列を戻すことができますが、その場合、URLには、ターゲットの表またはビューの単一行を識別する述語も含まれる必要があります。
例3-34に、これを示します。述語[DEPARTMENT_ID="10"]
句は、department_id
列に値10
が含まれるdepartments
行について、department_name
列の値を問合せで戻します。
SQL関数DBURIType
は、次の点でSQL/XML関数よりも柔軟性が低くなっています。
-
DBURITypeでは、生成された文書の形式を制御できません。
-
データは、単一の表またはビューからのみ生成できます。
-
生成される文書は、1つ以上の
ROW
要素で構成されます。各ROW
要素には、ターゲット表の列ごとの子が含まれます。 -
子要素の名前は、列の名前から導出されます。
XML要素の名前を制御する場合、複数の表からの列を含める場合、または生成される文書に含める表の列を制御する場合は、必要な列を単一行として公開するリレーショナル・ビューを作成してから、関数DBURIType
を使用して、そのビューのコンテンツからXML文書を生成します。
例3-32 DBURITypeおよびgetXML()を使用したリレーショナル表からのXMLデータの生成
SELECT DBURIType('/HR/DEPARTMENTS').getXML() FROM DUAL;
DBURITYPE('/HR/DEPARTMENTS').GETXML()
------------------------------------------------------
<?xml version="1.0"?>
<DEPARTMENTS>
<ROW>
<DEPARTMENT_ID>10</DEPARTMENT_ID>
<DEPARTMENT_NAME>Administration</DEPARTMENT_NAME>
<MANAGER_ID>200</MANAGER_ID>
<LOCATION_ID>1700</LOCATION_ID>
</ROW>
...
<ROW>
<DEPARTMENT_ID>20</DEPARTMENT_ID>
<DEPARTMENT_NAME>Marketing</DEPARTMENT_NAME>
<MANAGER_ID>201</MANAGER_ID>
<LOCATION_ID>1800</LOCATION_ID>
</ROW>
</DEPARTMENTS>
例3-33 XPath述語を使用した行の制限
SELECT DBURIType('/HR/DEPARTMENTS/ROW[DEPARTMENT_ID="10"]').getXML()
FROM DUAL;
DBURITYPE('/HR/DEPARTMENTS/ROW[DEPARTMENT_ID="10"]').GETXML()
------------------------------------------------------------------
<?xml version="1.0"?>
<ROW>
<DEPARTMENT_ID>10</DEPARTMENT_ID>
<DEPARTMENT_NAME>Administration</DEPARTMENT_NAME>
<MANAGER_ID>200</MANAGER_ID>
<LOCATION_ID>1700</LOCATION_ID>
</ROW>
1 row selected.
例3-34 XPath述語を使用した行と列の制限
SELECT DBURIType(
'/HR/DEPARTMENTS/ROW[DEPARTMENT_ID="10"]/DEPARTMENT_NAME').getXML()
FROM DUAL;
DBURITYPE('/HR/DEPARTMENTS/ROW[DEPARTMENT_ID="10"]/DEPARTMENT_NAME').GETXML()
-----------------------------------------------------------------------------
<?xml version="1.0"?>
<DEPARTMENT_NAME>Administration</DEPARTMENT_NAME>
1 row selected.
親トピック: リレーショナル・データからのXMLデータの生成
3.9 XML文書のキャラクタ・セット
XML文書で使用するキャラクタ・セットをOracle XML DBが決定する方法はいくつかあります
注意:
AL32UTF8は、XMLType
データに適したOracle Databaseキャラクタ・セットです。これはIANAの登録済標準であるUTF-8エンコーディングと同等であり、すべての有効なXML文字をサポートします。
Oracle Databaseのデータベース・キャラクタ・セットUTF8(ハイフンなし)とデータベース・キャラクタ・セットAL32UTF8またはキャラクタ・エンコーディングUTF-8を混同しないでください。データベース・キャラクタ・セットUTF8はAL32UTF8で置き換えられています。XMLデータにはUTF8を使用しないでください。キャラクタ・セットUTF8でサポートされるのはUnicodeバージョン3.1以下のみです。すべての有効なXML文字がサポートされるわけではありません。AL32UTF8には、このような制限はありません。
XMLデータにデータベース・キャラクタ・セットUTF8を使用すると、システムが停止したりセキュリティに悪影響を及ぼす可能性があります。入力した文書要素の名前にデータベース・キャラクタ・セットでサポートされない文字が含まれている場合、その文字は置換文字(通常は「?
」)で置き換えられます。このため、解析が終了して例外が発生します。リカバリ不能なエラーが発生する場合もあります。
- XMLエンコーディング宣言
XMLエンコーディング宣言を使用して、指定されたXMLエンティティで使用する文字エンコーディングを明示的に指定できます。 - XML文書をデータベースにロードするときのキャラクタ・セットの決定
文書がデータベースにロードされるときには、XMLデータがCLOB
値またはVARCHAR
値から取得される場合を除き、文字エンコーディングはエンコーディング宣言によって決まります。 - データベースからXML文書を取り出すときのキャラクタ・セットの決定
XMLデータがCLOB
値またはVARCHAR
値に格納されている場合を除き、これをSQLクライアント、プログラムAPIまたは転送プロトコルを使用してOracle XML DBから取り出す場合に使用するエンコーディングを指定できます。
親トピック: Oracle XML DBの使用方法の概要
3.9.1 XMLエンコーディング宣言
XMLエンコーディング宣言を使用して、指定されたXMLエンティティで使用する文字エンコーディングを明示的に指定できます。
各XML文書は、エンティティと呼ばれる単位で構成されます。XML文書内の各エンティティでは、その文字に対して異なるエンコーディングを使用できます。UTF-8またはUTF-16以外のエンコーディングで格納されるエンティティは、使用する文字コードを示すエンコーディング仕様が含まれたXML宣言で始まる必要があります。例:
<?xml version='1.0' encoding='EUC-JP' ?>
UTF-16でエンコードされたエンティティは、「XML 1.0 Reference」の付録Fで説明されているバイト・オーダー・マーク(BOM)で始まる必要があります。たとえば、大規模なendianのプラットフォームで、UTF-16データ・ストリームに必要なBOMは#xFEFF
です。
エンコーディング宣言およびBOMの両方が存在しない場合、XMLエンティティはUTF-8でエンコードされていると想定されます。ASCIIはUTF-8のサブセットであるため、ASCIIエンティティではエンコーディング宣言は必要ありません。
多くの場合、使用する文字コードの情報は、XMLデータ以外に外部ソースからも取得できます。たとえば、データのエンコーディングは、次に示すように、HTTP(S)リクエストのContent-Type
フィールドのcharset
パラメータから取得できます。
Content-Type: text/xml; charset=ISO-8859-4
親トピック: XML文書のキャラクタ・セット
3.9.2 XML文書をデータベースにロードするときのキャラクタ・セットの決定
文書がデータベースにロードされるときには、XMLデータがCLOB
値またはVARCHAR
値から取得される場合を除き、文字エンコーディングはエンコーディング宣言によって決まります。
XMLデータがCLOB
値またはVARCHAR
値から取得される場合、これらの2つのデータ型は常にデータベース・キャラクタ・セットでエンコードされるので、エンコーディング宣言の存在は無視されます。
さらに、プログラムAPIまたは転送プロトコルのいずれかを介してデータをOracle XML DBにロードするときは、外部エンコーディングを指定して文書のエンコーディング宣言をオーバーライドできます。XML Schemaに基づくXML文書に指定のエンコーディングに対して不適切な文字が含まれている場合、その文書をロードしようとするとエラーが発生します。
次の各例で、外部エンコーディングを指定するいくつかの方法を示します。
-
PL/SQLファンクション
DBMS_XDB_REPOS.createResource
を使用してBFILE
からファイル・リソースを作成する場合、CSID
引数でファイルのエンコーディングを指定できます。CSID
にゼロを指定すると、ファイルのエンコーディングは文書のエンコーディング宣言から自動検出されます。CREATE DIRECTORY xmldir AS '/private/xmldir'; CREATE OR REPLACE PROCEDURE loadXML(filename VARCHAR2, file_csid NUMBER) IS xbfile BFILE; RET BOOLEAN; BEGIN xbfile := bfilename('XMLDIR', filename); ret := DBMS_XDB_REPOS.createResource('/public/mypurchaseorder.xml', xbfile, file_csid); END;/
-
FTPプロトコルを使用して、文書をOracle XML DBにロードします。
quote set_charset
FTPコマンドを使用して、ロードするファイルのエンコーディングを指定します。ftp> quote set_charset Shift_JIS ftp> put mypurchaseorder.xml
-
HTTP(S)プロトコルを使用して、文書をOracle XML DBにロードします。Oracle XML DBに転送するデータのエンコーディングは、リクエスト・ヘッダー内に指定します。
Content-Type: text/xml; charset= EUC-JP
親トピック: XML文書のキャラクタ・セット
3.9.3 データベースからXML文書を取り出すときのキャラクタ・セットの決定
XMLデータがCLOB
値またはVARCHAR
値に格納されている場合を除き、これをSQLクライアント、プログラムAPIまたは転送プロトコルを使用してOracle XML DBから取り出す場合に使用するエンコーディングを指定できます。
XMLデータがCLOB
値またはVARCHAR2
値として格納されていると、エンコーディング宣言がある場合、その宣言は、格納と同様に取出しでも常に無視されます。したがって、取り出す文書のエンコーディングは、その文書で明示的に宣言されているエンコーディングとは異なる場合があります。
データベースから取り出されるXML文書のキャラクタ・セットは、次の方法で決定されます。
-
SQLクライアント: XMLの取出しに(SQL*Plusなどの)SQLクライアントが使用される場合、キャラクタ・セットはクライアント側の環境変数
NLS_LANG
によって決定されます。特に、XMLデータ自体にキャラクタ・セットが明示的に宣言されていても、この設定のほうが優先されます。たとえば、クライアント側の
NLS_LANG
変数をAMERICAN_AMERICA.AL32UTF8
に設定し、宣言<?xml version="1.0" encoding="EUC-JP"?>
で指定されたエンコーディングEUC_JP
のXML文書を取得する場合、取得される文書のキャラクタ・セットはEUC_JP
ではなく、AL32UTF8
となります。 -
PL/SQLおよびAPI: PL/SQLまたはプログラムAPIを使用すると、XMLデータを
VARCHAR
、CLOB
またはXMLType
データ型で取り出すことができます。SQLクライアントの場合、NLS_LANG
を設定することにより、取り出すデータのエンコーディングを制御できます。また、
XMLType
およびURIType
メソッドを使用して、XMLデータをBLOB
値で取り出すこともできます。これにより、BLOB
値のキャラクタ・セットを指定できます。次はその例です。CREATE OR REPLACE FUNCTION getXML(pathname VARCHAR2, charset VARCHAR2) RETURN BLOB IS xblob BLOB; BEGIN SELECT XMLSERIALIZE(DOCUMENT e.RES AS BLOB ENCODING charset) INTO xblob FROM RESOURCE_VIEW e WHERE equals_path(e.RES, pathname) = 1; RETURN xblob; END; /
-
FTP: FTP
quote set_nls_locale
コマンドを使用して、キャラクタ・セットを設定できます。ftp> quote set_nls_locale EUC-JP ftp> get mypurchaseorder.xml
-
HTTP(S): HTTP(S)リクエストで
Accept-Charset
パラメータを使用できます。/httptest/mypurchaseorder.xml 1.1 HTTP/Host: localhost:2345 Accept: text/* Accept-Charset: iso-8859-1, utf-8
脚注の説明
脚注1:XML Schemaに基づくデータのXMLType
記憶域モデルは、参照するXML Schemaの登録時に指定したものです。登録時に記憶域モデルが指定されなかった場合、オブジェクト・リレーショナル記憶域が使用されます。