12 PL/SQLパッケージDBMS_XMLSTORE

PL/SQLパッケージDBMS_XMLSTOREを使用して、オブジェクト・リレーショナル形式で格納されているXML文書でデータを挿入、更新または削除できます。これは、パッケージDBMS_XMLGENによって生成されるマッピングに類似した正規のXMLマッピングを使用します。これは、マッピングをオブジェクト・リレーショナルの構造体に変換し、対応する値をリレーショナル表で挿入、更新または削除します。

12.1 DBMS_XMLSTOREパッケージの使用

コンテキスト・ハンドルを作成し、1つ以上の挿入、更新または削除を実行して、コンテキストを閉じます。

PL/SQLパッケージDBMS_XMLSTOREを使用するには、次のステップを実行します。

  1. DBMS_XMLSTORE.newContext関数をコールし、DML操作に使用する表名を指定してコンテキスト・ハンドルを作成します。大/小文字を区別する場合は、関数に渡す文字列に二重引用符(")で囲みます。

    デフォルトでは、XML文書は<ROW>タグで行を識別します。これは、XMLデータの生成時にDBMS_XMLGENパッケージで使用されるデフォルトと同じです。この動作は、setRowTag関数を使用してオーバーライドできます。

  2. (オプション) 1つ以上の挿入、更新または削除を実行します(このステップは繰り返すことができます)。
    • 挿入の場合、パフォーマンスを向上させるには、列ごとにDBMS_XMLSTORE.setUpdateColumnプロシージャをコールして、挿入する列リストを指定できます。デフォルト動作では(列のリストを指定しない場合)、対応する要素がXML文書内に存在しているすべての列に値が挿入されます。

    • 更新の場合、関数DBMS_XMLSTORE.setKeyColumnを使用して(疑似)キー列を1つ以上指定します。これらは、更新するを指定するために使用されます。SQLのUPDATE文のWHERE句でこれを行います。指定する列は、表のキーである必要はありませんが、更新する行を一意に指定する必要があります。

      たとえば、employees表のemployee_id列は、行を一意に識別します(表のキーです)。表の更新に使用するXML文書に、<EMPLOYEE_ID>2176</EMPLOYEE_ID>要素が含まれている場合、employee_id2176と等しい行が更新されます。

      パフォーマンスを向上させるために、DBMS_XMLSTORE.setUpdateColumnを使用して、update列のリストを指定することもできます。デフォルト動作では、対応する要素がXML文書に存在するsetKeyColumnによって識別される行内のすべての列が更新されます。

    • 削除の場合、削除する行を識別するために、(擬似)キー列を指定します。これは更新する行の指定と同じ方法で行います(前述を参照)。

  3. DBMS_XMLSTORE関数のinsertXMLupdateXMLまたはdeleteXMLに文書を指定します。このステップを複数のXML文書に対して繰り返すことができます。
  4. DBMS_XMLSTORE.closeContext関数をコールしてコンテキストをクローズします。

12.2 DBMS_XMLSTOREを使用したXML文書の挿入

PL/SQLパッケージDBMS_XMLSTOREを使用して、XML文書を表またはビューに挿入できます。これにより、文書が解析されて、値のバインド先のINSERT文が作成されます。デフォルトでは、XML文書内の要素で表されるすべての列に値が挿入されます。

例12-1では、DBM_XMLSTOREを使用して、2人の新入社員に関する情報をemployees表に挿入します。挿入する情報は、XMLデータとして提供されています。

例12-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.

12.3 DBMS_XMLSTOREを使用したXMLデータの更新

PL/SQLパッケージDBMS_XMLSTOREを使用して、既存のデータを更新(変更)できます。行を識別するのにまとめて使用される列ごとsetKeyColumnプロシージャを1回ずつコールして、更新する行を指定します。(SQLでは、UPDATE文のWHERE句を使用して行を指定します。)

この列のセットは、キー列と同様に機能し、組み合せて使用することにより、更新する一意の行を指定します。ただし、(setKeyColumnとともに)使用する列は、表内のキーである必要はありません。行を一意に指定するかぎり、setKeyColumnへのコールとともに使用できます。

例12-2では、DBM_XMLSTOREを使用して情報を更新します。この例では、従業員番号188の名前が誤って「Kelly」として記録されていると仮定し、この名前を「Pat」に訂正します。employee_id列が、employees表の主キーであるため、更新用に一意の行を識別するには、employee_id列を指定するsetKeyColumnへの1回のコールで十分です。

次のUPDATE文は、例12-2で使用されているDBM_XMLSTOREと同等です。

UPDATE hr.employees SET first_name = 'Pat' WHERE employee_id = 188; 

例12-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.

12.4 DBMS_XMLSTOREを使用したXMLデータの削除

PL/SQLパッケージDBMS_XMLSTOREを使用して、既存のデータを削除できます。行を識別するのにまとめて使用される列ごとsetKeyColumnプロシージャを1回ずつコールして、削除する行を指定します。(SQLでは、UPDATE文のWHERE句を使用して行を指定します。)

例12-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.