この章では、PL/SQLパッケージDBMS_XMLSTOREについて説明します。このパッケージは、オブジェクト・リレーショナル表のXML文書に対するデータの挿入、更新および削除に使用されます。
この章の内容は次のとおりです。
DBMS_XMLSTOREパッケージを使用すると、XMLを使用して、リレーショナル表でDML操作を実行できます。DBMS_XMLGENで生成されるマッピングと同様に正規XMLマッピングを使用し、それをオブジェクト・リレーショナルの構成に変換し、リレーショナル表に対して値を挿入、更新または削除します。
DBMS_XMLSTOREパッケージの機能は、Oracle XML SQL Utility(XSU)の一部であるDBMS_XMLSAVEパッケージと類似しています。ただし、いくつか重要な違いがあります。
DBMS_XMLSTOREはCで作成されてカーネルにコンパイルされるため、優れたパフォーマンスが得られます。
DBMS_XMLSTOREは、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句を使用して、更新する行を一意に識別する列の組合せを指定します。setKeyColumnとともに使用する列は、表内のキーである必要はありません。行を一意に指定するかぎり、使用可能です。
たとえば、employees表のemployee_id列は、行を一意に識別します(表のキーです)。表の更新に使用するXML文書に、<EMPLOYEE_ID>2176</EMPLOYEE_ID>要素が含まれている場合、employee_idが2176と等しい行が更新されます。
DBMS_XMLSTORE.setUpdateColumnを使用して、update列のリストを指定することもできます。パフォーマンス向上のためにこの方法をお薦めします。デフォルト動作では、対応する要素がXML文書に存在するsetKeyColumnによって識別される行内のすべての列が更新されます。
削除の場合: 更新の場合と同様、削除する行を識別するために、(擬似)キー列を指定する必要があります。
PL/SQL関数のinsertXML、updateXMLまたはdeleteXMLに文書を指定します。
この最後の手順を複数のXML文書に対して繰り返すことができます。
表またはビューにXML文書を挿入するには、表名またはビュー名、および文書を指定します。DBMS_XMLSTOREによって文書が解析され、すべての値がバインドされるINSERT文が作成されます。デフォルトでは、DBMS_XMLSTOREによって、XML文書内の要素で表されるすべての列に値が挿入されます。
例13-1 指定した列でのデータの挿入
この例では、DBM_XMLSTOREを使用して、2人の新入社員に関する情報をemployees表に挿入します。この情報は、XMLデータ形式で提供されます。
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へのコールとともに使用できます。
例13-2 キー列を使用したデータの更新
この例では、DBM_XMLSTOREを使用して情報を更新します。この例では、従業員番号188の名前が誤って「Kelly」として記録されていると仮定し、この名前を「Pat」に訂正します。employee_id列が、employees表の主キーであるため、更新用に一意の行を識別するには、employee_id列を指定するsetKeyColumnへの1回のコールで十分です。
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文は、この例で使用されているDBM_XMLSTOREと同等です。
UPDATE hr.employees SET first_name = 'Pat' WHERE employee_id = 188;
削除の場合は、更新の場合と同様、削除する行を識別するキー、または擬似キー列を指定します。
例13-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.