この章では、PL/SQLパッケージDBMS_XMLSTORE
について説明します。このパッケージは、オブジェクト・リレーショナル表のXML文書に対するデータの挿入、更新および削除に使用されます。
この章の内容は次のとおりです。
PL/SQLパッケージDBMS_XMLSTORE
を使用すると、XMLを使用して、リレーショナル表でDML操作を実行できます。パッケージDBMS_XMLGEN
で生成されるマッピングと同様に正規XMLマッピングを使用し、それをオブジェクト・リレーショナルの構成に変換し、リレーショナル表に対して対応する値を挿入、更新または削除します。
パッケージDBMS_XMLSTORE
の機能は、Oracle XML SQL Utility(XSU)の一部であるDBMS_XMLSAVE
パッケージと類似しています。ただし、いくつか重要な違いがあります。
DBMS_XMLSTORE
はCで作成されてカーネルにコンパイルされるため、優れたパフォーマンスが得られます。
DBMS_XMLSTORE
は、Simple API for XML(SAX)を使用して入力XML文書を解析するため、拡張性が高く、メモリー要件が低減します。DBMS_XMLSTORE
では、CLOB
およびVARCHAR
に加え、XMLType
データを入力できます。
DBMS_XMLSAVE
にも存在するPL/SQL関数のinsertXML
、updateXML
およびdeleteXML
が、DBMS_XMLSTORE
では、CLOB
値と文字列の他にXMLType
インスタンスを取るように拡張されています。この結果、Oracle XML DB機能との緊密な統合が実現します。
PL/SQLパッケージDBMS_XMLSTORE
を使用するには、次の手順を実行します。
DBMS_XMLSTORE
.newContext()
関数をコールし、DML操作に使用する表名を指定してコンテキスト・ハンドルを作成します。大/小文字を区別する場合は、関数に渡す文字列を二重引用符("
)で囲みます。
デフォルトでは、XML文書は<ROW>
タグで行を識別します。これは、XMLデータの生成時にDBMS_XMLGEN
パッケージで使用されるデフォルトと同じです。この動作は、setRowTag
関数を使用してオーバーライドできます。
挿入の場合、パフォーマンスを向上させるには、列ごとにDBMS_XMLSTORE.
setUpdateColumn
プロシージャをコールして、挿入する列リストを設定できます。デフォルト動作では(列のリストを指定しない場合)、対応する要素がXML文書内に存在しているすべての列に値が挿入されます。
更新の場合、関数DBMS_XMLSTORE.
setKeyColumn
を使用して(擬似)キー列を1つ以上指定します。これらは、更新する行を指定するために使用されます。SQLのUPDATE
文のWHERE
句でこれを行います。指定する列は、表のキーである必要はありませんが、更新する行を一意に指定する必要があります。
たとえば、employees
表のemployee_id
列は、行を一意に識別します(表のキーです)。表の更新に使用するXML文書に、<EMPLOYEE_ID>2176</EMPLOYEE_ID>
要素が含まれている場合、employee_id
が2176
と等しい行が更新されます。
パフォーマンスを向上させるために、DBMS_XMLSTORE.setUpdateColumn
を使用して、update列のリストを指定することもできます。デフォルト動作では、対応する要素がXML文書に存在するsetKeyColumn
によって識別される行内のすべての列が更新されます。
削除の場合、削除する行を識別するために、(擬似)キー列を指定します。これは更新する行の指定と同じ方法で行います。手順3を参照してください。
PL/SQL関数のinsertXML
、updateXML
またはdeleteXML
に文書を指定します。この手順を複数のXML文書に対して繰り返すことができます。
表またはビューにXML文書を挿入するには、表名またはビュー名、および文書を指定します。DBMS_XMLSTORE
によって文書が解析され、すべての値がバインドされるINSERT
文が作成されます。デフォルトでは、DBMS_XMLSTORE
によって、XML文書内の要素で表されるすべての列に値が挿入されます。
例14-1では、DBM_XMLSTORE
を使用して、2人の新入社員に関する情報をemployees
表に挿入します。この情報は、XMLデータ形式で提供されます。
例14-1 指定した列でのデータの挿入
SELECT employee_id AS EMP_ID, salary, hire_date, job_id, email, last_name FROM employees WHERE department_id = 30; EMP_ID SALARY HIRE_DATE JOB_ID EMAIL LAST_NAME ------ ---------- --------- ---------- ---------- ---------- 114 11000 07-DEC-94 PU_MAN DRAPHEAL Raphaely 115 3100 18-MAY-95 PU_CLERK AKHOO Khoo 116 2900 24-DEC-97 PU_CLERK SBAIDA Baida 117 2800 24-JUL-97 PU_CLERK STOBIAS Tobias 118 2600 15-NOV-98 PU_CLERK GHIMURO Himuro 119 2500 10-AUG-99 PU_CLERK KCOLMENA Colmenares 6 rows selected. DECLARE insCtx DBMS_XMLSTORE.ctxType; rows NUMBER; xmlDoc CLOB := '<ROWSET> <ROW num="1"> <EMPLOYEE_ID>920</EMPLOYEE_ID> <SALARY>1800</SALARY> <DEPARTMENT_ID>30</DEPARTMENT_ID> <HIRE_DATE>17-DEC-2002</HIRE_DATE> <LAST_NAME>Strauss</LAST_NAME> <EMAIL>JSTRAUSS</EMAIL> <JOB_ID>ST_CLERK</JOB_ID> </ROW> <ROW> <EMPLOYEE_ID>921</EMPLOYEE_ID> <SALARY>2000</SALARY> <DEPARTMENT_ID>30</DEPARTMENT_ID> <HIRE_DATE>31-DEC-2004</HIRE_DATE> <LAST_NAME>Jones</LAST_NAME> <EMAIL>EJONES</EMAIL> <JOB_ID>ST_CLERK</JOB_ID> </ROW> </ROWSET>'; BEGIN insCtx := DBMS_XMLSTORE.newContext('HR.EMPLOYEES'); -- Get saved context DBMS_XMLSTORE.clearUpdateColumnList(insCtx); -- Clear the update settings -- Set the columns to be updated as a list of values DBMS_XMLSTORE.setUpdateColumn(insCtx, 'EMPLOYEE_ID'); DBMS_XMLSTORE.setUpdateColumn(insCtx, 'SALARY'); DBMS_XMLSTORE.setUpdateColumn(insCtx, 'HIRE_DATE'); DBMS_XMLSTORE.setUpdateColumn(insCtx, 'DEPARTMENT_ID'); DBMS_XMLSTORE.setUpdateColumn(insCtx, 'JOB_ID'); DBMS_XMLSTORE.setUpdateColumn(insCtx, 'EMAIL'); DBMS_XMLSTORE.setUpdateColumn(insCtx, 'LAST_NAME'); -- Insert the doc. rows := DBMS_XMLSTORE.insertXML(insCtx, xmlDoc); DBMS_OUTPUT.put_line(rows || ' rows inserted.'); -- Close the context DBMS_XMLSTORE.closeContext(insCtx); END; / 2 rows inserted. PL/SQL procedure successfully completed. SELECT employee_id AS EMP_ID, salary, hire_date, job_id, email, last_name FROM employees WHERE department_id = 30; EMP_ID SALARY HIRE_DATE JOB_ID EMAIL LAST_NAME ------ ---------- --------- ---------- ---------- ---------- 114 11000 07-DEC-94 PU_MAN DRAPHEAL Raphaely 115 3100 18-MAY-95 PU_CLERK AKHOO Khoo 116 2900 24-DEC-97 PU_CLERK SBAIDA Baida 117 2800 24-JUL-97 PU_CLERK STOBIAS Tobias 118 2600 15-NOV-98 PU_CLERK GHIMURO Himuro 119 2500 10-AUG-99 PU_CLERK KCOLMENA Colmenares 920 1800 17-DEC-02 ST_CLERK STRAUSS Strauss 921 2000 31-DEC-04 ST_CLERK EJONES Jones 8 rows selected.
DBMS_XMLSTORE
パッケージを使用して既存のデータを更新(変更)するには、更新する行を指定する必要があります。SQLでは、UPDATE
文のWHERE
を使用してこの操作を実行します。DBMS_XMLSTORE
では、行を識別するのにまとめて使用される列ごとにsetKeyColumn
プロシージャを1回ずつコールして実行します。
この列のセットは、キー列と同様に機能し、組み合せて使用することにより、更新する一意の行を指定します。ただし、(setKeyColumn
とともに)使用する列は、表内のキーである必要はありません。行を一意に指定するかぎり、setKeyColumn
へのコールとともに使用できます。
例14-2では、DBM_XMLSTORE
を使用して情報を更新します。この例では、従業員番号188の名前が誤って「Kelly」として記録されていると仮定し、この名前を「Pat」に訂正します。employee_id
列が、employees
表の主キーであるため、更新用に一意の行を識別するには、employee_id
列を指定するsetKeyColumn
への1回のコールで十分です。
例14-2 キー列を使用したデータの更新
SELECT employee_id, first_name FROM employees WHERE employee_id = 188; EMPLOYEE_ID FIRST_NAME ----------- ---------- 188 Kelly 1 row selected. DECLARE updCtx DBMS_XMLSTORE.ctxType; rows NUMBER; xmlDoc CLOB := '<ROWSET> <ROW> <EMPLOYEE_ID>188</EMPLOYEE_ID> <FIRST_NAME>Pat</FIRST_NAME> </ROW> </ROWSET>'; BEGIN updCtx := DBMS_XMLSTORE.newContext('HR.EMPLOYEES'); -- get the context DBMS_XMLSTORE.clearUpdateColumnList(updCtx); -- clear update settings -- Specify that column employee_id is a "key" to identify the row to update. DBMS_XMLSTORE.setKeyColumn(updCtx, 'EMPLOYEE_ID'); rows := DBMS_XMLSTORE.updateXML(updCtx, xmlDoc); -- update the table DBMS_XMLSTORE.closeContext(updCtx); -- close the context END; / SELECT employee_id, first_name FROM employees WHERE employee_id = 188; EMPLOYEE_ID FIRST_NAME ----------- ---------- 188 Pat 1 row selected.
次のUPDATE
文は、例14-2で使用されているDBM_XMLSTORE
と同等です。
UPDATE hr.employees SET first_name = 'Pat' WHERE employee_id = 188;
削除の場合は、更新の場合と同様、削除する行を識別するキー、または疑似キー列を指定します。
例14-3 DBMS_XMLSTORE.DELETEXMLの例
SELECT employee_id FROM employees WHERE employee_id = 188;
EMPLOYEE_ID
-----------
188
1 row selected.
DECLARE
delCtx DBMS_XMLSTORE.ctxType;
rows NUMBER;
xmlDoc CLOB :=
'<ROWSET>
<ROW>
<EMPLOYEE_ID>188</EMPLOYEE_ID>
<DEPARTMENT_ID>50</DEPARTMENT_ID>
</ROW>
</ROWSET>';
BEGIN
delCtx := DBMS_XMLSTORE.newContext('HR.EMPLOYEES');
DBMS_XMLSTORE.setKeyColumn(delCtx, 'EMPLOYEE_ID');
rows := DBMS_XMLSTORE.deleteXML(delCtx, xmlDoc);
DBMS_XMLSTORE.closeContext(delCtx);
END;
/
SELECT employee_id FROM employees WHERE employee_id = 188;
no rows selected.