ヘッダーをスキップ
Oracle XML DB開発者ガイド
11gリリース1(11.1)
E05669-02
  目次
目次
索引
索引

戻る
戻る
 
次へ
次へ
 

19 XMLTypeビュー

この章では、XMLTypeビューを作成および使用する方法を説明します。

この章の内容は次のとおりです。

XMLTypeビューの概要

XMLTypeビューは、既存のリレーショナル・データおよびオブジェクト・リレーショナル・データをXML形式でラップします。XMLTypeビューを使用する主なメリットは次のとおりです。

XMLTypeビューは、オブジェクト・ビューに類似しています。XMLTypeビューの各行は、XMLTypeインスタンスに対応しています。ビュー内の各行を一意に識別するためのオブジェクト識別子は、XMLType値に対して、getNumberVal()を指定したextractなどの関数を使用して作成できます。OBJECT IDENTIFIER句では、XMLTypeメソッドのextract()ではなくSQLファンクションextractを使用することをお薦めします。

この章では、XML Schemaとは、W3CのXML Schema 1.0勧告(http://www.w3.org/XML/Schema)のことを指します。

XMLTypeビューには2つのタイプがあります。

XMLTypeビューに対する問合せのXPathリライトは、XML Schemaに基づくXMLTypeビューとXML Schemaに基づかないXMLTypeビューの両方で可能です。XPathリライトの詳細は、「XMLTypeビューでのXPathリライト」で説明しています。

XML Schemaに基づくXMLTypeビューを作成するには、最初にXML Schemaを登録します。ビューがオブジェクト・ビューである場合、つまりオブジェクト型を使用して構成されている場合、XML Schemaには、XMLとSQLオブジェクト型の間の双方向マッピングを表す注釈が必要です。その後、適切なSQLオブジェクト型のインスタンスを構築する基礎となる問合せを指定することによって、登録されたXML Schemaに準拠するXMLTypeビューを作成できます。

XMLTypeビューは、次の方法で構成できます。

XMLTypeビューの作成: 構文

図19-1に、XMLTypeビューを作成するためのCREATE VIEW句を示します。CREATE VIEWの構文の詳細は、『Oracle Database SQL言語リファレンス』を参照してください。

図19-1 XMLTypeビューの作成の句: 構文

図19-1の説明が続きます
「図19-1 XMLTypeビューの作成の句: 構文」の説明

XML Schemaに基づかないXMLTypeビューの作成

XML Schemaに基づかないXMLTypeビューでは、結果として戻されるXML値が、登録されたXML Schema内の特定の要素に制限されません。XML Schemaに基づかないXMLTypeを作成するには、主に2つの方法があります。

SQL/XML生成関数の使用によるXML Schemaに基づかないXMLTypeビューの作成

例19-1 に、SQL/XML関数XMLELement()を使用してXMLTypeビューを作成する方法を示します。

例19-1 XMLELEMENTを使用したXMLTypeビューの作成

次の文は、SQL関数XMLElementを使用してXMLTypeビューを作成します。

CREATE OR REPLACE VIEW emp_view OF XMLType WITH OBJECT ID
  (extract(OBJECT_VALUE, '/Emp/@empno').getnumberval())
  AS SELECT XMLElement("Emp",
                       XMLAttributes(employee_id),
                       XMLForest(e.first_name ||' '|| e.last_name AS "name",
                                 e.hire_date AS "hiredate"))
       AS "result"
       FROM employees e
       WHERE salary > 15000;

SELECT * FROM emp_view;

SYS_NC_ROWINFO$
-------------------------------------------------------------------------------------
<Emp EMPLOYEE_ID="100"><name>Steven King</name><hiredate>1987-06-17</hiredate></Emp>
<Emp EMPLOYEE_ID="101"><name>Neena Kochhar</name><hiredate>1989-09-21</hiredate></Emp>
<Emp EMPLOYEE_ID="102"><name>Lex De Haan</name><hiredate>1993-01-13</hiredate></Emp>

文書内のempno属性は、各行に一意の識別子として使用されます。XPathリライトの結果、XPath式/Emp/@empnoempno列を直接参照できます。

リレーショナル表またはリレーショナル・ビュー内の既存のデータは、このメカニズムを使用してXMLとして公開できます。ビューがSQL/XML生成関数によって生成されると、XPath式を使用してそのビューにアクセスする問合せは、多くの場合、最適化されます(リライトされます)。最適化された問合せは、基礎となるリレーショナル列に直接アクセスできます。「XMLTypeビューでのXPathリライト」を参照してください。

これらのXMLTypeビューに対してDML操作を行うことができますが、通常、DML操作を処理するためにINSTEAD OFトリガーを作成する必要があります。

SYS_XMLGENでオブジェクト型を使用してスキーマに基づかないXMLTypeビューを作成する方法

オブジェクト型を指定したSQL関数sys_XMLGenを使用して、XMLTypeビューを作成することもできます。関数sys_XMLGenはオブジェクト型を入力してXMLTypeを生成します。sys_XMLGenを使用して同じ問合せ結果を生成する同等の問合せを次に示します。

例19-2 オブジェクト型およびSYS_XMLGENを使用したXMLTypeビューの作成

CREATE TYPE emp_t AS OBJECT ("@empno"  NUMBER(6),
                             fname     VARCHAR2(20),
                             lname     VARCHAR2(25),
                             hiredate  DATE);
/
CREATE OR REPLACE VIEW employee_view OF XMLType
  WITH OBJECT ID (extract(OBJECT_VALUE, '/Emp/@empno').getnumberval()) AS
  SELECT sys_XMLGen(emp_t(e.employee_id, e.first_name, e.last_name, e.hire_date),
                    XMLFormat('EMP'))
       FROM employees e
       WHERE salary > 15000;

SELECT * FROM employee_view;

SYS_NC_ROWINFO$
--------------------------------------------------------
<?xml version="1.0"?
<EMP empno="100">
  <FNAME>Steven</FNAME>
  <LNAME>King</LNAME>
  <HIREDATE>17-JUN-87</HIREDATE>
</EMP>

<?xml version="1.0"?>
<EMP empno="101">
  <FNAME>Neena</FNAME>
  <LNAME>Kochhar</LNAME>
  <HIREDATE>21-SEP-89</HIREDATE>
</EMP>

<?xml version="1.0"?>
<EMP empno="102">
  <FNAME>Lex</FNAME>
  <LNAME>De Haan</LNAME>
  <HIREDATE>13-JAN-93</HIREDATE>
</EMP>

リレーショナル表、リレーショナル・ビュー、オブジェクト・リレーショナル表またはオブジェクト・リレーショナル・ビュー内の既存のデータは、このメカニズムを使用してXMLとして公開できます。また、単純なXPath検索を含む、SQL関数extractextractValue、およびexistsNodeを使用した、sys_XMLGenによって生成されたビューへの問合せは、XPathリライトの対象になります。XPathリライトは、基礎となるオブジェクト属性またはリレーショナル列への直接アクセスを容易にします。

XML Schemaに基づくXMLTypeビューの作成

XML Schemaに基づくXMLTypeビューでは、結果として戻されるXML値が、登録されたXML Schema内の特定の要素に制限されます。XML Schemaに基づくXMLTypeを作成するには、主に2つの方法があります。

SQL/XML生成関数の使用によるXML Schemaに基づくXMLTypeビューの作成

SQL/XML生成関数を使用すると、「XML Schemaに基づかないXMLTypeビューの作成」の項で説明したXML Schemaに基づかない場合と同様の方法で、XML Schemaに基づくXMLTypeビューを作成できます。XML Schemaに基づくXMLTypeビューを作成するには、次の手順を実行します。

  1. 必要なXML構造を含むXML Schema文書を作成および登録します。XMLTypeビューはSQL/XML生成関数を使用して構成されているため、XMLとSQLオブジェクト型間のマッピングを表す注釈をXML Schemaに付ける必要がないことに注意してください。

  2. SQL/XML関数を使用して、そのXML Schemaに準拠するXMLTypeビューを作成します。

この2つの手順を、それぞれ例19-3および例19-4に示します。

例19-3 XML Schema emp_simple.xsdの登録

従業員を定義するXML構造を含むemp_simple.xsdというXML Schemaがあると想定します。この例は、XML Schemaを登録し、URLを使用して識別する方法を示しています。

BEGIN
  DBMS_XMLSCHEMA.registerSchema('http://www.oracle.com/emp_simple.xsd',
    '<schema xmlns="http://www.w3.org/2001/XMLSchema"
             targetNamespace="http://www.oracle.com/emp_simple.xsd" version="1.0"
             xmlns:xdb="http://xmlns.oracle.com/xdb"
             elementFormDefault="qualified">
       <element name = "Employee">
         <complexType>
           <sequence>
             <element name = "EmployeeId" type = "positiveInteger"/>
             <element name = "Name" type = "string"/>
             <element name = "Job" type = "string"/>
             <element name = "Manager" type = "positiveInteger"/>
             <element name = "HireDate" type = "date"/>
             <element name = "Salary" type = "positiveInteger"/>
             <element name = "Commission" type = "positiveInteger"/>
             <element name = "Dept">
               <complexType>
                 <sequence>
                   <element name = "DeptNo" type = "positiveInteger" />
                   <element name = "DeptName" type = "string"/>
                   <element name = "Location" type = "positiveInteger"/>
                 </sequence>
               </complexType>
             </element>
           </sequence>
         </complexType>
       </element>
     </schema>',
    TRUE,
    TRUE,
    FALSE);
END;

この文によって、XML Schemaが次の目的の場所に登録されます。

http://www.oracle.com/emp_simple.xsd

SQL/XML関数を使用して、XML Schemaに基づくXMLTypeビューを作成できます。結果として戻されるXMLデータは、このビューに指定したXML Schemaに準拠している必要があります。

SQL/XML関数を使用してXML Schemaに基づくコンテンツを生成する場合、すべての要素に適切な名前空間情報を指定し、xsi:schemaLocation属性を使用してスキーマの場所を指定する必要があります。これらは、XMLAttributes句を使用して指定できます。

例19-4 SQL/XML関数を使用したXMLTypeビューの作成

CREATE OR REPLACE VIEW emp_simple_xml OF XMLType
  XMLSCHEMA "http://www.oracle.com/emp_simple.xsd" ELEMENT "Employee"
   WITH OBJECT ID (extract(OBJECT_VALUE,
                           '/Employee/EmployeeId/text()').getnumberval()) AS
   SELECT
     XMLElement("Employee",
                XMLAttributes(
                  'http://www.oracle.com/emp_simple.xsd' AS "xmlns",
                  'http://www.w3.org/2001/XMLSchema-instance' AS "xmlns:xsi",
                  'http://www.oracle.com/emp_simple.xsd
                   http://www.oracle.com/emp_simple.xsd'
                  AS "xsi:schemaLocation"),
                XMLForest(e.employee_id     AS "EmployeeId",
                          e.last_name       AS "Name",
                          e.job_id          AS "Job",
                          e.manager_id      AS "Manager",
                          e.hire_date       AS "HireDate",
                          e.salary          AS "Salary",
                          e.commission_pct  AS "Commission",
                          XMLForest(
                            d.department_id     AS "DeptNo",
                            d.department_name  AS "DeptName",
                            d.location_id      AS "Location") AS "Dept"))
     FROM employees e, departments d
     WHERE e.department_id = d.department_id;

例19-4では、XMLElementEmployee XML要素を作成し、その内部のXMLForest関数コールはEmployee要素の子を作成しています。XMLElement内のXMLAttributes句によって、生成されたXMLがビューのXML Schemaに準拠するように、必須のXML namespaceおよびスキーマのlocation属性が作成されます。最も内側にあるXMLForest関数のコールによって、Employee要素内にネストされたdepartment XML要素が作成されます。

XML生成関数は、デフォルトではXML Schemaに基づかないXMLインスタンスを生成します。ただし、スキーマ位置が属性xsi:schemaLocationまたはxsi:noNamespaceSchemaLocationを使用して指定されている場合は、Oracle XML DBによってXML Schemaに基づくXMLが生成されます。XMLTypeビューの場合は、要素と属性の名前がXML Schema内の要素と属性の名前に一致しているかぎり、このXMLが有効なXML Schemaに基づく文書に暗黙的に変換されます。生成されたXMLデータで発生したエラーは、XMLインスタンス上で検証や抽出などの操作が実行されたときに検出されます。

例19-5 XMLTypeビューの問合せ

この例では、XMLTypeビューを問い合せて、employeesおよびdepartments表からXMLの結果が戻されています。問合せの結果は、ここではわかりやすくするためフォーマット出力しています。

SELECT OBJECT_VALUE AS RESULT FROM emp_simple_xml WHERE ROWNUM < 2;

RESULT
---------------------------------------------------------------------
<Employee xmlns="http://www.oracle.com/emp_simple.xsd"
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:schemaLocation="http://www.oracle.com/emp_simple.xsd
                              http://www.oracle.com/emp_simple.xsd">
  <EmployeeId>200</EmployeeId>
  <Name>Whalen</Name>
  <Job>AD_ASST</Job>
  <Manager>101</Manager>
  <HireDate>1987-09-17</HireDate>
  <Salary>4400</Salary>
  <Dept>
    <DeptNo>10</Deptno>
    <DeptName>Administration</DeptName>
    <Location>1700</Location>
  </Dept>
</Employee>

SQL/XML関数での名前空間の使用

複数の名前空間を含む複合XML Schemaが存在する場合は、SQL/XML関数で提供される部分的にエスケープされたマッピングを使用して、適切な名前空間と接頭辞を持つ要素を作成する必要があります。

例19-6 XMLTypeビューでの名前空間接頭辞の使用

SELECT  XMLElement("ipo:Employee",
          XMLAttributes('http://www.oracle.com/emp_simple.xsd' AS "xmlns:ipo",
                        'http://www.oracle.com/emp_simple.xsd
                         http://www.oracle.com/emp_simple.xsd' AS "xmlns:xsi"),
            XMLForest(e.employee_id AS "ipo:EmployeeId",
                      e.last_name   AS "ipo:Name",
                      e.job_id      AS "ipo:Job",
                      e.manager_id  AS "ipo:Manager",
                      TO_CHAR(e.hire_date,'YYYY-MM-DD') AS "ipo:HireDate",
                      e.salary  AS "ipo:Salary",
                      e.commission_pct AS "ipo:Commission",
                 XMLForest(d.department_id   AS "ipo:DeptNo",
                           d.department_name AS "ipo:DeptName", d.location_id
       AS "ipo:Location") AS "ipo:Dept"))
       FROM employees e, departments d
       WHERE e.department_id = d.department_id
             AND d.department_id = 20;
BEGIN
  -- Delete schema if it already exists (else error)
  DBMS_XMLSCHEMA.deleteSchema('emp-noname.xsd', 4);
END;

このSQL問合せによって、正しい名前空間、接頭辞およびターゲット・スキーマの場所を持つXMLインスタンスが作成され、emp_simple_xmlビューの定義で問合せとして使用できます。この問合せによって次のようなインスタンスが作成されます。

result
----------
<ipo:Employee
xmlns:ipo="http://www.oracle.com/emp_simple.xsd"
 xmlns:xsi="http://www.oracle.com/emp_simple.xsd
 http://www.oracle.com/emp_simple.xsd">
<ipo:EmployeeId>201</ipo:EmployeeId><ipo:Name>Hartstein</ipo:Name>
<ipo:Job>MK_MAN</ipo:Job><ipo:Manager>100</ipo:Manager>
<ipo:HireDate>1996-02-17</ipo:HireDate><ipo:Salary>13000</ipo:Salary>
<ipo:Dept><ipo:DeptNo>20</ipo:DeptNo><ipo:DeptName>Marketing</ipo:DeptName>
<ipo:Location>1800</ipo:Location></ipo:Dept></ipo:Employee>
<ipo:Employee xmlns:ipo="http://www.oracle.com/emp_simple.xsd"
 xmlns:xsi="http://www.oracle.com/emp_simple.xsd
 http://www.oracle.com/emp_simple.xsd"><ipo:EmployeeId>202</ipo:EmployeeId>
<ipo:Name>Fay</ipo:Name><ipo:Job>MK_REP</ipo:Job><ipo:Manager>201</ipo:Manager>
<ipo:HireDate>1997-08-17</ipo:HireDate><ipo:Salary>6000</ipo:Salary>
<ipo:Dept><ipo:DeptNo>20</ipo:Dept
No><ipo:DeptName>Marketing</ipo:DeptName><ipo:Location>1800</ipo:Location>
</ipo:Dept>
</ipo:Employee>

XML Schemaにターゲットの名前空間が存在しない場合は、xsi:noNamespaceSchemaLocation属性を使用してターゲットの名前空間を示すことができます。たとえば、emp-noname.xsdという場所に登録された次のXML Schemaについて考えてみます。

BEGIN
  DBMS_XMLSCHEMA.registerSchema(
    'emp-noname.xsd',
    '<schema xmlns="http://www.w3.org/2001/XMLSchema"
             xmlns:xdb="http://xmlns.oracle.com/xdb">
       <element name = "Employee">
         <complexType>
           <sequence>
             <element name = "EmployeeId" type = "positiveInteger"/>
             <element name = "Name" type = "string"/>
             <element name = "Job" type = "string"/>
             <element name = "Manager" type = "positiveInteger"/>
             <element name = "HireDate" type = "date"/>
             <element name = "Salary" type = "positiveInteger"/>
             <element name = "Commission" type = "positiveInteger"/>
             <element name = "Dept">
               <complexType>
                 <sequence>
                   <element name = "DeptNo" type = "positiveInteger" />
                   <element name = "DeptName" type = "string"/>
                   <element name = "Location" type = "positiveInteger"/>
                 </sequence>
               </complexType>
             </element>
           </sequence>
         </complexType>
       </element>
     </schema>',
    TRUE,
    TRUE,
    FALSE);
END;

次の文によって、このXML Schemaに準拠するビューが作成されます。

CREATE OR REPLACE VIEW emp_xml OF XMLType
     XMLSCHEMA "emp-noname.xsd" ELEMENT "Employee"
     WITH OBJECT ID (extract(OBJECT_VALUE,
                             '/Employee/EmployeeId/text()').getnumberval()) AS
     SELECT XMLElement(
       "Employee",
       XMLAttributes('http://www.w3.org/2001/XMLSchema-instance' AS "xmlns:xsi",
                     'emp-noname.xsd' AS "xsi:noNamespaceSchemaLocation"),
       XMLForest(e.employee_id    AS "EmployeeId",
                 e.last_name      AS "Name",
                 e.job_id         AS "Job",
                 e.manager_id     AS "Manager",
                 e.hire_date      AS "HireDate",
                 e.salary         AS "Salary",
                 e.commission_pct AS "Commission",
                 XMLForest(d.department_id     AS "DeptNo",
                            d.department_name  AS "DeptName",
                            d.location_id      AS "Location") AS "Dept"))
       FROM employees e, departments d
       WHERE e.department_id = d.department_id;

XMLAttributes句によって、noNamespaceスキーマの場所属性を含むXML要素が作成されます。

例19-7 XML Schemaに基づくXMLTypeビューでのSQL/XML生成関数の使用

BEGIN
  -- Delete schema if it already exists (else error)
  DBMS_XMLSCHEMA.deleteSchema('http://www.oracle.com/dept.xsd', 4);
END;
/
BEGIN
DBMS_XMLSCHEMA.registerSchema(
  'http://www.oracle.com/dept.xsd',
  '<schema xmlns="http://www.w3.org/2001/XMLSchema"
           targetNamespace="http://www.oracle.com/dept.xsd" version="1.0"
           xmlns:xdb="http://xmlns.oracle.com/xdb"
           elementFormDefault="qualified">
     <element name = "Department">
       <complexType>
         <sequence>
           <element name = "DeptNo" type = "positiveInteger"/>
           <element name = "DeptName" type = "string"/>
           <element name = "Location" type = "positiveInteger"/>
           <element name = "Employee" maxOccurs = "unbounded">
             <complexType>
               <sequence>
                 <element name = "EmployeeId" type = "positiveInteger"/>
                 <element name = "Name" type = "string"/>
                 <element name = "Job" type = "string"/>
                 <element name = "Manager" type = "positiveInteger"/>
                 <element name = "HireDate" type = "date"/>
                 <element name = "Salary" type = "positiveInteger"/>
                 <element name = "Commission" type = "positiveInteger"/>
               </sequence>
             </complexType>
           </element>
         </sequence>
       </complexType>
     </element>
   </schema>',
  TRUE,
  FALSE,
  FALSE);
END;
/
CREATE OR REPLACE VIEW dept_xml OF XMLType
  XMLSCHEMA "http://www.oracle.com/dept.xsd" ELEMENT "Department"
  WITH OBJECT ID (extract(OBJECT_VALUE, '/Department/DeptNo').getNumberVal()) AS
         SELECT  XMLElement(
           "Department",
           XMLAttributes(
             'http://www.oracle.com/emp.xsd' AS "xmlns" ,
             'http://www.w3.org/2001/XMLSchema-instance' AS "xmlns:xsi",
             'http://www.oracle.com/dept.xsd
              http://www.oracle.com/dept.xsd' AS "xsi:schemaLocation"),
           XMLForest(d.department_id "DeptNo",
                     d.department_name "DeptName",
                     d.location_id "Location"),
           (SELECT Xmlagg(XMLElement("Employee",
                               XMLForest(e.employee_id  "EmployeeId",
                                    e.last_name "Name",
                                    e.job_id "Job",
                                    e.manager_id "Manager",
               to_char(e.hire_date,'YYYY-MM-DD') "Hiredate",
                                    e.salary "Salary",
                                    e.commission_pct "Commission")))
                 FROM employees e
                 WHERE e.department_id = d.department_id))
     FROM departments d;

このSQL問合せによって、正しい名前空間、接頭辞およびターゲット・スキーマの場所を持つXMLインスタンスが作成され、emp_simple_xmlビューの定義で問合せとして使用できます。この問合せによって次のようなインスタンスが作成されます。

SELECT OBJECT_VALUE AS result FROM dept_xml WHERE ROWNUM < 2;

RESULT
----------------------------------------------------------------
<Department
    xmlns="http://www.oracle.com/emp.xsd"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.oracle.com/dept.xsd
                        http://www.oracle.com/dept.xsd">
  <DeptNo>10</DeptNo>
  <DeptName>Administration</DeptName>
  <Location>1700</Location>
  <Employee>
    <EmployeeId>200</EmployeeId>
    <Name>Whalen</Name>
    <Job>AD_ASST</Job>
    <Manager>101</Manager>
    <Hiredate>1987-09-17</Hiredate>
    <Salary>4400</Salary>
  </Employee>
</Department>

オブジェクト型とオブジェクト・ビューの使用によるXML SchemaベースのXMLTypeビューの作成

厳密な型指定を持つXMLを含むリレーショナル・データまたはオブジェクト・リレーショナル・データをラップするには、オブジェクト・ビューを使用して、次の手順を実行します。

  1. オブジェクト型を作成します。

  2. XML構造を含むXML Schema文書を作成(または生成)し、SQLオブジェクト型および属性へのマッピングとともに登録します。XML Schemaは既存のオブジェクト型から生成でき、XMLとオブジェクト型との間のマッピングが含まれるように注釈を付ける必要があります。

    XML Schemaを登録する前に、オプションのOracle XML DB属性を指定できます。この場合、Oracleによって追加情報が検証され、Oracle XML DB属性に指定した値が他のXML Schema宣言と互換性があるかどうかが確認されます。この形式のXML Schema登録は、通常、XMLTypeビューを使用して既存のデータをラップするときに行われます。


    関連項目:

    この処理の詳細は、第6章「XML Schemaの格納と問合せ: 基本」を参照してください。

    PL/SQL関数DBMS_XMLSchema.generateSchemaおよびDBMS_XMLSchema.generateSchemasを使用して、指定したオブジェクト型に対するデフォルトのXMLマッピングを生成できます。生成されたXML Schema文書には、SQLTypeSQLSchemaなどの属性が指定されています。その後、これらのXML Schema文書を登録すると、次の検証フォームが生成されます。

    • simpleTypeに基づく属性または要素に対するSQLType:これは、対応するXMLTypeと互換性があります。たとえば、XML文字列のデータ型は、VARCHAR2またはラージ・オブジェクト(LOB)データ型にのみマップされます。

    • complexTypeに基づく要素に対して指定されたSQLType:これは、LOBまたはcomplexTypeの宣言と互換性がある構造を持つオブジェクト型のいずれかです。オブジェクト型には、正しいデータ型を持つ正しい数の属性が含まれます。

  3. XMLTypeビューを作成し、XML SchemaのURLおよびルート要素名を指定します。基礎となるビュー問合せによって、まずオブジェクト・インスタンスが作成され、これらのインスタンスがXMLに変換されます。この手順は、次の2つの手順でも実行できます。

    1. オブジェクト・ビューを作成します。

    2. そのオブジェクト・ビューのXMLTypeビューを作成します。

たとえば、従業員と部門のリレーショナル表、およびこのデータのXMLビューに基づく次の項を見てみます。

オブジェクト・ビューからの、XML Schemaに基づくXMLTypeビューの作成

1つ目の例では、手順1から手順4bまでを実行して、ネストした部門情報を含む従業員のリレーショナル・データをXMLとしてラップします。

手順1: オブジェクト型の作成

例19-8は、ビューに対応するオブジェクト型を作成しています。

例19-8 XML Schemaに基づくXMLTypeビューに対応するオブジェクト型の作成

CREATE TYPE dept_t AS OBJECT
      (deptno        NUMBER(4),
       dname         VARCHAR2(30),
       loc           NUMBER(4));
/

CREATE TYPE emp_t AS OBJECT
      (empno         NUMBER(6),
       ename         VARCHAR2(25),
       job           VARCHAR2(10),
       mgr           NUMBER(6),
       hiredate      DATE,
       sal           NUMBER(8,2),
       comm          NUMBER(2,2),
       dept          dept_t );
/
手順2: XML Schema emp.xsdの作成または生成

XML Schemaは、手動で作成するか、またはパッケージDBMS_XMLSCHEMAを使用して既存のオブジェクト型から自動的に作成します。例19-9を参照してください。

例19-9 DBMS_XMLSCHEMA.GENERATESCHEMAによるXML Schemaの生成

SELECT DBMS_XMLSCHEMA.generateSchema('HR','EMP_T') AS result FROM DUAL;

この問合せによって、employee型のXML Schemaが生成されます。このファンクションには、名前空間を追加するためなどの、様々な引数を指定できます。このXML Schemaを編集して、生成された様々なデフォルトのマッピングを変更することもできます。関数DBMS_XMLSCHEMA.generateSchemasは、任意のレベルに埋め込まれているオブジェクト型とその属性が参照するSQLデータベース・スキーマごとに、1つのXML Schemaのリストを生成します。

手順3. XML Schema emp_complex.xsdの登録

XML Schema emp_complex.xsdは、XML要素および属性を、オブジェクト型の対応する属性にマップする方法も指定します。例19-10は、XML Schema emp_complex.xsdの登録方法を示しています。例19-10xdb:SQLTypeの注釈も参照してください。

例19-10 XML Schema emp_complex.xsdの登録

BEGIN
  -- Delete schema if it already exists (else error)
  DBMS_XMLSCHEMA.deleteSchema('http://www.oracle.com/emp_complex.xsd', 4);
END;
/

COMMIT;

BEGIN
  DBMS_XMLSCHEMA.registerSchema(
    'http://www.oracle.com/emp_complex.xsd',
    '<?xml version="1.0"?>
    <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
                xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                xmlns:xdb="http://xmlns.oracle.com/xdb"
                xsi:schemaLocation="http://xmlns.oracle.com/xdb
                                    http://xmlns.oracle.com/xdb/XDBSchema.xsd">
      <xsd:element name="Employee" type="EMP_TType" xdb:SQLType="EMP_T"
                   xdb:SQLSchema="HR"/>
      <xsd:complexType name="EMP_TType" xdb:SQLType="EMP_T" xdb:SQLSchema="HR"
                       xdb:maintainDOM="false">
        <xsd:sequence>
          <xsd:element name="EMPNO" type="xsd:double" xdb:SQLName="EMPNO"
                       xdb:SQLType="NUMBER"/>
          <xsd:element name="ENAME" xdb:SQLName="ENAME" xdb:SQLType="VARCHAR2">
            <xsd:simpleType>
              <xsd:restriction base="xsd:string">
                <xsd:maxLength value="25"/>
              </xsd:restriction>
            </xsd:simpleType>
          </xsd:element>
          <xsd:element name="JOB" xdb:SQLName="JOB" xdb:SQLType="VARCHAR2">
            <xsd:simpleType>
              <xsd:restriction base="xsd:string">
                <xsd:maxLength value="10"/>
              </xsd:restriction>
            </xsd:simpleType>
          </xsd:element>
          <xsd:element name="MGR" type="xsd:double" xdb:SQLName="MGR"
                       xdb:SQLType="NUMBER"/>
          <xsd:element name="HIREDATE" type="xsd:date" xdb:SQLName="HIREDATE"
                       xdb:SQLType="DATE"/>
          <xsd:element name="SAL" type="xsd:double" xdb:SQLName="SAL"
                       xdb:SQLType="NUMBER"/>
          <xsd:element name="COMM" type="xsd:double" xdb:SQLName="COMM"
                       xdb:SQLType="NUMBER"/>
          <xsd:element name="DEPT" type="DEPT_TType" xdb:SQLName="DEPT"
                       xdb:SQLSchema="HR" xdb:SQLType="DEPT_T"/>
        </xsd:sequence>
      </xsd:complexType>
      <xsd:complexType name="DEPT_TType" xdb:SQLType="DEPT_T" xdb:SQLSchema="HR"
                       xdb:maintainDOM="false">
        <xsd:sequence>
          <xsd:element name="DEPTNO" type="xsd:double" xdb:SQLName="DEPTNO"
                       xdb:SQLType="NUMBER"/>
          <xsd:element name="DNAME" xdb:SQLName="DNAME" xdb:SQLType="VARCHAR2">
            <xsd:simpleType>
              <xsd:restriction base="xsd:string">
                <xsd:maxLength value="30"/>
              </xsd:restriction>
            </xsd:simpleType>
          </xsd:element>
         <xsd:element name="LOC" type="xsd:double" xdb:SQLName="LOC"
                       xdb:SQLType="NUMBER"/>
        </xsd:sequence>
      </xsd:complexType>
    </xsd:schema>',
   TRUE,
   FALSE,
   FALSE);
END;
/

この文によって、XML Schemaが次の目的の場所に登録されます。

"http://www.oracle.com/emp_complex.xsd"
手順4a:1ステップ・プロセスの使用

1ステップ・プロセスでは、リレーショナル表にXMLTypeビューを作成します。例19-11を参照してください。

例19-11 XMLTypeビューの作成

CREATE OR REPLACE VIEW emp_xml OF XMLType
  XMLSCHEMA "http://www.oracle.com/emp_complex.xsd"
  ELEMENT "Employee"
    WITH OBJECT ID (extractValue(OBJECT_VALUE, '/Employee/EMPNO')) AS
  SELECT emp_t(e.employee_id, e.last_name, e.job_id, e.manager_id, e.hire_date,
               e.salary, e.commission_pct,
               dept_t(d.department_id, d.department_name, d.location_id))
    FROM employees e, departments d
    WHERE e.department_id = d.department_id;

この例では、ここでOBJECT ID句にSQL関数extractValueを使用します。これは、extractValueが、XML Schema情報を使用して適切なSQLデータ型マッピング(この場合はSQLのNUMBER型)を自動的に判断できるためです。XMLTypeメソッドのextractValue()ではなくSQL関数extractValueを使用することをお薦めします。

手順4b:最初にオブジェクト・ビューを作成する2ステップ・プロセスの使用

2ステップ・プロセスでは、まずオブジェクト・ビューを作成し、次にそのオブジェクト・ビューにXMLTypeビューを作成します。例19-12を参照してください。

例19-12 オブジェクト・ビューの作成と、そのオブジェクト・ビューへのXMLTypeビューの作成

CREATE OR REPLACE VIEW emp_v OF emp_t WITH OBJECT ID (empno) AS
  SELECT emp_t(e.employee_id, e.last_name, e.job_id, e.manager_id, e.hire_date,
               e.salary, e.commission_pct,
               dept_t(d.department_id, d.department_name, d.location_id))
    FROM employees e, departments d
    WHERE e.department_id = d.department_id;

CREATE OR REPLACE VIEW emp_xml OF XMLType
  XMLSCHEMA "http://www.oracle.com/emp_complex.xsd" ELEMENT "Employee"
  WITH OBJECT ID DEFAULT
  AS SELECT VALUE(p) FROM emp_v p;

ネストした従業員データを含む部門のリレーショナル・データのXMLとしてのラッピング

2つ目の例では、手順1から手順3bまでを実行して、ネストした従業員情報を含む部門のリレーショナル・データをXMLとしてラップします。

手順1: オブジェクト型の作成

最初の手順は、必要な型の作成です。例19-13を参照してください。

例19-13 オブジェクト型の作成

CREATE TYPE emp_t AS OBJECT (empno         NUMBER(6),
                             ename         VARCHAR2(25),
                             job           VARCHAR2(10),
                             mgr           NUMBER(6),
                             hiredate      DATE,
                             sal           NUMBER(8,2),
                             comm          NUMBER(2,2)); /
CREATE OR REPLACE TYPE emplist_t AS TABLE OF emp_t;
/
CREATE TYPE dept_t AS OBJECT (deptno        NUMBER(4),
                              dname         VARCHAR2(30),
                              loc           NUMBER(4),
                              emps          emplist_t);
/
手順2: XML Schema dept_complex.xsdの登録

既存のXML Schemaを使用するか、または関数DBMS_XMLSCHEMA.generateSchemaまたはDBMS_XMLSCHEMA.generateSchemasを使用してオブジェクト型からXML Schemaを生成します。例19-14は、XML Schema dept_complex.xsdの登録方法を示しています。

例19-14 XML Schema dept_complex.xsdの登録

BEGIN
  -- Delete schema if it already exists (else error)
  DBMS_XMLSCHEMA.deleteSchema('http://www.oracle.com/dept_complex.xsd', 4);
END;
/
BEGIN
 DBMS_XMLSCHEMA.registerSchema('http://www.oracle.com/dept_complex.xsd',
   '<?xml version="1.0"?>
   <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
               xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
               xmlns:xdb="http://xmlns.oracle.com/xdb"
               xsi:schemaLocation="http://xmlns.oracle.com/xdb
                                   http://xmlns.oracle.com/xdb/XDBSchema.xsd">
     <xsd:element name="Department" type="DEPT_TType" xdb:SQLType="DEPT_T"
                  xdb:SQLSchema="HR"/>
     <xsd:complexType name="DEPT_TType" xdb:SQLType="DEPT_T" xdb:SQLSchema="HR"
                      xdb:maintainDOM="false">
       <xsd:sequence>
         <xsd:element name="DEPTNO" type="xsd:double" xdb:SQLName="DEPTNO"
                      xdb:SQLType="NUMBER"/>
         <xsd:element name="DNAME" xdb:SQLName="DNAME" xdb:SQLType="VARCHAR2">
           <xsd:simpleType>
             <xsd:restriction base="xsd:string">
               <xsd:maxLength value="30"/>
             </xsd:restriction>
           </xsd:simpleType>
         </xsd:element>
         <xsd:element name="LOC" type="xsd:double" xdb:SQLName="LOC"
                      xdb:SQLType="NUMBER"/>
         <xsd:element name="EMPS" type="EMP_TType" maxOccurs="unbounded"
                      minOccurs="0" xdb:SQLName="EMPS"
                      xdb:SQLCollType="EMPLIST_T" xdb:SQLType="EMP_T"
                      xdb:SQLSchema="HR" xdb:SQLCollSchema="HR"/>
       </xsd:sequence>
     </xsd:complexType>
     <xsd:complexType name="EMP_TType" xdb:SQLType="EMP_T" xdb:SQLSchema="HR"
                      xdb:maintainDOM="false">
       <xsd:sequence>
         <xsd:element name="EMPNO" type="xsd:double" xdb:SQLName="EMPNO"
                      xdb:SQLType="NUMBER"/>
         <xsd:element name="ENAME" xdb:SQLName="ENAME" xdb:SQLType="VARCHAR2">
           <xsd:simpleType>
             <xsd:restriction base="xsd:string">
               <xsd:maxLength value="25"/>
             </xsd:restriction>
           </xsd:simpleType>
         </xsd:element>
         <xsd:element name="JOB" xdb:SQLName="JOB" xdb:SQLType="VARCHAR2">
           <xsd:simpleType>
             <xsd:restriction base="xsd:string">
               <xsd:maxLength value="10"/>
             </xsd:restriction>
           </xsd:simpleType>
         </xsd:element>
         <xsd:element name="MGR" type="xsd:double" xdb:SQLName="MGR"
                      xdb:SQLType="NUMBER"/>
         <xsd:element name="HIREDATE" type="xsd:date" xdb:SQLName="HIREDATE"
                      xdb:SQLType="DATE"/>
         <xsd:element name="SAL" type="xsd:double" xdb:SQLName="SAL"
                      xdb:SQLType="NUMBER"/>
         <xsd:element name="COMM" type="xsd:double" xdb:SQLName="COMM"
                      xdb:SQLType="NUMBER"/>
       </xsd:sequence>
     </xsd:complexType>
   </xsd:schema>',
  TRUE,
  FALSE,
  FALSE);
END;
/
手順3a:リレーショナル表のXMLTypeビューの作成

次の手順は部門オブジェクト型からのdept_xml XMLTypeビューの作成です。例19-15を参照してください。

例19-15 リレーショナル表へのXMLTypeビューの作成

CREATE OR REPLACE VIEW dept_xml OF XMLType
  XMLSChema "http://www.oracle.com/dept_complex.xsd" ELEMENT "Department"
  WITH OBJECT ID (extractValue(OBJECT_VALUE, '/Department/DEPTNO')) AS
  SELECT dept_t(d.department_id, d.department_name, d.location_id,
                CAST(MULTISET(SELECT emp_t(e.employee_id, e.last_name, e.job_id,
                                           e.manager_id, e.hire_date,
                                           e.salary, e.commission_pct)
                                FROM employees e
                                WHERE e.department_id = d.department_id)
                       AS emplist_t))
    FROM departments d;
手順3b:SQL/XML関数を使用したXMLTypeビューの作成

オブジェクト型の定義を使用せずに、SQL/XML生成関数を使用してリレーショナル表からdept_xml XMLTypeビューを作成することもできます。例19-16を参照してください。

例19-16 SQL/XML関数を使用したXMLTypeビューの作成

CREATE OR REPLACE VIEW dept_xml OF XMLType
  XMLSCHEMA "http://www.oracle.com/dept_complex.xsd" ELEMENT "Department"
  WITH OBJECT ID (extract(OBJECT_VALUE, '/Department/DEPTNO').getNumberVal()) AS
  SELECT
    XMLElement(
      "Department",
      XMLAttributes('http://www.oracle.com/dept_complex.xsd' AS "xmlns",
                    'http://www.w3.org/2001/XMLSchema-instance' AS "xmlns:xsi",
                    'http://www.oracle.com/dept_complex.xsd
                     http://www.oracle.com/dept_complex.xsd'
                      AS "xsi:schemaLocation"),
      XMLForest(d.department_id "DeptNo", d.department_name "DeptName",
                d.location_id "Location"),
      (SELECT XMLAgg(XMLElement("Employee",
                                XMLForest(e.employee_id "EmployeeId",
                                          e.last_name "Name",
                                          e.job_id "Job",
                                          e.manager_id "Manager",
                                          e.hire_date "Hiredate",
                                          e.salary "Salary",
                                          e.commission_pct "Commission")))
                      FROM employees e WHERE e.department_id = d.department_id))
    FROM departments d;

注意:

XML Schemaおよび要素情報は、ビュー・レベルで指定する必要があります。これは、SELECTリストでは、基礎となる表から別のXML SchemaのXMLが任意で作成される可能性があるためです。

XMLType表からのXMLTypeビューの作成

たとえば、いくつかの述語を使用して、XMLを変換したり、戻される行を制限することによって、XMLType表のXMLTypeビューを作成できます。

例19-17 XMLType表の行の制限によるXMLTypeビューの作成

次の例では、基礎となるXMLType表から戻される行を制限して、XMLTypeビューを作成します。この例では、「ネストした従業員データを含む部門のリレーショナル・データのXMLとしてのラッピング」で説明したdept_complex.xsd XML Schemaを使用して、基礎となる表を作成しています。

CREATE TABLE dept_xml_tab OF XMLType
    XMLSchema "http://www.oracle.com/dept_complex.xsd" ELEMENT "Department"
    NESTED TABLE XMLDATA."EMPS" STORE AS dept_xml_tab_tab1;

CREATE OR REPLACE VIEW dallas_dept_view OF XMLType
    XMLSchema "http://www.oracle.com/dept.xsd" ELEMENT "Department"
        AS SELECT OBJECT_VALUE FROM dept_xml_tab
           WHERE extractValue(OBJECT_VALUE, '/Department/Location') = 'DALLAS';

dallas_dept_viewによって、XMLType表の行が、所在地がダラスである部門に制限されます。

例19-18は、スタイルシートを使用してXMLデータを変換することによって、XMLTypeビューを作成する方法を示しています。

例19-18 XMLType表の変換によるXMLTypeビューの作成

CREATE OR REPLACE VIEW hr_po_tab OF XMLType
  ELEMENT "PurchaseOrder"
  WITH OBJECT ID DEFAULT
  AS SELECT XMLtransform(OBJECT_VALUE, x.col1)
       FROM purchaseorder p, xsl_tab x;

SQL関数REFを使用したXMLTypeビュー・オブジェクトの参照

XMLTypeビュー・オブジェクトは、SQL関数refを使用して参照できます。

SELECT ref(d) FROM dept_xml_tab d;

XMLTypeビュー参照は、次のいずれかのオブジェクトIDに基づきます。

これらのREFは、OCIオブジェクト・キャッシュ内のOCIXMLTypeインスタンスをフェッチするために使用できます。また、SQL問合せ内でも使用できます。これらのREFは、オブジェクト・ビューへのREFと同様に動作します。

XMLTypeビューでのデータ操作言語(DML)

本来、XMLTypeビューは更新可能でありません。そのため、すべてのデータ操作(DML)を処理するには、INSTEAD-OF TRIGGERSを作成する必要があります。基礎となるビュー問合せを分析することによって、ビューが暗黙的に更新可能な場合を識別できます。

例19-19 暗黙的に更新可能なビューの識別

XMLTypeビューが暗黙的に更新可能である場合を識別する1つの方法は、XMLTypeビュー問合せを使用して、そのビューが、本来更新可能であるオブジェクト・ビューまたはオブジェクト・コンストラクタに基づいているかどうかを判断することです。次に例を示します。

CREATE TYPE dept_t AS OBJECT
      (deptno NUMBER(4),
       dname VARCHAR2(30),
       loc NUMBER(4));
/
BEGIN
  -- Delete schema if it already exists (else error)
  DBMS_XMLSCHEMA.deleteSchema('http://www.oracle.com/dept.xsd', 4);
END;
/
COMMIT;

BEGIN
  DBMS_XMLSCHEMA.registerSchema('http://www.oracle.com/dept_t.xsd',
    '<?xml version="1.0"?>
     <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
                 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                 xmlns:xdb="http://xmlns.oracle.com/xdb"
                 xsi:schemaLocation="http://xmlns.oracle.com/xdb
                                     http://xmlns.oracle.com/xdb/XDBSchema.xsd">
     <xsd:element name="Department" type="DEPT_TType" xdb:SQLType="DEPT_T"
                    xdb:SQLSchema="HR"/>
     <xsd:complexType name="DEPT_TType" xdb:SQLType="DEPT_T" xdb:SQLSchema="HR"
                        xdb:maintainDOM="false">
         <xsd:sequence>
           <xsd:element name="DEPTNO" type="xsd:double" xdb:SQLName="DEPTNO"
                        xdb:SQLType="NUMBER"/>
           <xsd:element name="DNAME" xdb:SQLName="DNAME" xdb:SQLType="VARCHAR2">
             <xsd:simpleType>
               <xsd:restriction base="xsd:string">
                 <xsd:maxLength value="30"/>
               </xsd:restriction>
             </xsd:simpleType>
           </xsd:element>
           <xsd:element name="LOC" type="xsd:double" xdb:SQLName="LOC"
                xdb:SQLType="NUMBER"/>
         </xsd:sequence>
       </xsd:complexType>
     </xsd:schema>',
    TRUE,
    FALSE,
    FALSE);
END;
/
CREATE OR REPLACE VIEW dept_xml of XMLType
  XMLSchema "http://www.oracle.com/dept_t.xsd" element "Department"
  WITH OBJECT ID (OBJECT_VALUE.extract('/Department/DEPTNO').getnumberval()) AS
  SELECT dept_t(d.department_id, d.department_name, d.location_id)
    FROM departments d;

INSERT INTO dept_xml
  VALUES (
    XMLType.createXML(
      '<Department
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:noNamespaceSchemaLocation="http://www.oracle.com/dept_t.xsd" >
         <DEPTNO>300</DEPTNO>
         <DNAME>Processing</DNAME>
         <LOC>1700</LOC>
       </Department>'));

UPDATE dept_xml d
 SET d.OBJECT_VALUE = updateXML(d.OBJECT_VALUE, '/Department/DNAME/text()',
                                'Shipping')
   WHERE existsNode(d.OBJECT_VALUE, '/Department[DEPTNO=300]') = 1;

XMLTypeビューでのXPathリライト

オブジェクト型、オブジェクト・ビューまたはSQL関数sys_XMLGenを使用して構成されたXMLTypeビューでのXPathリライトは、通常のXMLType表の列のXPathリライトと同じです。したがって、ビュー列に対するSQL関数extractexistsNode、およびextractValueは、パフォーマンスを向上させるために、基礎となるリレーショナル・アクセスまたはオブジェクト・リレーショナル・アクセスにリライトされます。

SQL/XMLを使用して構成されたXMLTypeビューでのXPathリライトもサポートされています。ビュー列に対する関数extractexistsNode、およびextractValueは、パフォーマンスを向上させるために、基礎となるリレーショナル・アクセスにリライトされます。

SQL/XML生成関数で作成したビュー

この項では、SQL/XML関数を使用して構成されたXMLTypeビューのXML Schemaに基づくXPathリライトおよびXML Schemaに基づかないXPathリライトについて説明します。

SQL/XMLを使用して構成されたXML Schemaに基づかないビューでのXPathリライト

例19-20に、XML Schemaに基づかないXMLTypeビューでのXPathリライトを示します。

例19-20 SQL/XMLを使用して構成されたXML Schemaに基づかないビュー

CREATE OR REPLACE VIEW emp_view OF XMLType
  WITH OBJECT ID (extract(OBJECT_VALUE, '/Emp/@empno').getnumberval())
  AS SELECT XMLElement("Emp", XMLAttributes(employee_id),
                       XMLForest(e.first_name ||' '|| e.last_name AS "name",
                                 e.hire_date AS "hiredate")) AS "result"
       FROM employees e
       WHERE salary > 15000;
  • SQL関数extractValueを使用してemp_viewから選択する問合せ

    SELECT extractValue(OBJECT_VALUE, '/Emp/name'),
           extractValue(OBJECT_VALUE, '/Emp/hiredate'
      FROM emp_view;
    

    この問合せは次のようになります。

     SELECT e.first_name ||' '|| e.last_name, e.hire_date FROM employees e
       WHERE e.salary > 15000;
    

    リライトされた問合せは、単純なリレーショナル問合せです。extractValue式は、ビューemp_viewで定義されているとおりに、リレーショナル列アクセスにリライトされます。

  • SQL関数extractValueに続けてメソッドgetNumberVal()を使用してemp_viewから選択する問合せ

    SELECT (extract(OBJECT_VALUE, '/Emp/@empno').getnumberval()) FROM emp_view;
    

    この問合せは次のようになります。

    SELECT e.employee_id FROM employees e WHERE e.salary > 15000;
    

    リライトされた問合せは、単純なリレーショナル問合せです。extract式とその後のgetNumberVal()は、ビューemp_viewで定義されているとおりに、リレーショナル列アクセスにリライトされます。

  • SQL関数existsNodeを使用してビューemp_viewから選択する問合せ

    SELECT extractValue(OBJECT_VALUE, '/Emp/name'),
           extractValue(OBJECT_VALUE, '/Emp/hiredate')
      FROM emp_view WHERE existsNode(OBJECT_VALUE, '/Emp[@empno=101]') = 1;
    

    この問合せは次のようになります。

    SELECT e.first_name ||' '|| e.last_name, e.hire_date
      FROM employees e
      WHERE e.employee_id = 101 AND e.salary > 15000;
    

    リライトされた問合せは、単純なリレーショナル問合せです。existsNode式のXPath述語は、ビューemp_viewで定義されているとおりに、リレーショナル列に対する述語にリライトされます。

    employees.empno列に索引が作成されている場合、問合せオプティマイザは、問合せを高速化するために索引を使用できます。

    existsNodeを使用してビューemp_viewから選択する問合せ

    SELECT extractValue(OBJECT_VALUE, '/Emp/name'),
           extractValue(OBJECT_VALUE, '/Emp/hiredate'),
           extractValue(OBJECT_VALUE, '/Emp/@empno')
      FROM emp_view
      WHERE existsNode(OBJECT_VALUE, '/Emp[name="Steven King" or @empno = 101] ')
            = 1;
    

    この問合せは次のようになります。

    SELECT e.first_name ||' '|| e.last_name, e.hire_date, e.employee_id
      FROM employees e
      WHERE (e.first_name ||' '|| e.last_name = 'Steven King'
             OR e.employee_id = 101)
        AND e.salary > 15000;
    

    リライトされた問合せは、単純なリレーショナル問合せです。existsNode式のXPath述語は、ビューemp_viewで定義されているとおりに、リレーショナル列に対する述語にリライトされます。

  • extractを使用してビューemp_viewから選択する問合せ

    SELECT extract(OBJECT_VALUE, '/Emp/name'),
           extract(OBJECT_VALUE, '/Emp/hiredate')
      FROM emp_view;
    

    この問合せは次のようになります。

    SELECT CASE WHEN e.first_name ||' '|| e.last_name IS NOT NULL THEN
           XMLElement("name",e.first_name ||' '|| e.last_name) ELSE NULL END,
           CASE WHEN e.hire_date IS NOT NULL
                THEN XMLElement("hiredate", e.hire_date)
           ELSE NULL END
      FROM employees e WHERE e.salary > 15000;
    

    リライトされた問合せは、単純なリレーショナル問合せです。extract式は、リレーショナル列に対する式にリライトされます。


    注意:

    ビューでは、nameおよびhiredate要素を表すためにSQL関数XMLForestが使用されるため、リライトされた問合せでは、XMLForestセマンティクスと一貫するように同等のCASE式が使用されます。

SQL/XMLを使用して構成されたXML Schemaに基づくビューでのXPathリライト

例19-21に、SQL/XML関数を使用して構成されたXML Schemaに基づくXMLTypeビューでのXPathリライトを示します。

例19-21 SQL/XMLを使用して構成されたXML Schemaに基づくビュー

BEGIN
  -- Delete schema if it already exists (else error)
  DBMS_XMLSCHEMA.deleteSchema('http://www.oracle.com/emp_simple.xsd', 4);
END;
/

BEGIN
 DBMS_XMLSCHEMA.registerSchema(
   'http://www.oracle.com/emp_simple.xsd',
   '<schema
        xmlns="http://www.w3.org/2001/XMLSchema"
        targetNamespace="http://www.oracle.com/emp_simple.xsd" version="1.0"
        xmlns:xdb="http://xmlns.oracle.com/xdb"
        elementFormDefault="qualified">
      <element name = "Employee">
        <complexType>
          <sequence>
            <element name = "EmployeeId" type = "positiveInteger"/>
            <element name = "Name" type = "string"/>
            <element name = "Job" type = "string"/>
            <element name = "Manager" type = "positiveInteger"/>
            <element name = "HireDate" type = "date"/>
            <element name = "Salary" type = "positiveInteger"/>
            <element name = "Commission" type = "positiveInteger"/>
            <element name = "Dept">
              <complexType>
                <sequence>
                  <element name = "DeptNo" type = "positiveInteger" />
                  <element name = "DeptName" type = "string"/>
                  <element name = "Location" type = "positiveInteger"/>
                </sequence>
              </complexType>
            </element>
          </sequence>
        </complexType>
      </element>
    </schema>',
   TRUE,
   TRUE,
   FALSE);
END;
/

CREATE OR REPLACE VIEW emp_xml OF XMLType
  XMLSCHEMA "http://www.oracle.com/emp_simple.xsd" ELEMENT "Employee"
  WITH OBJECT ID (extract(OBJECT_VALUE,
                  '/Employee/EmployeeId/text()').getnumberval()) AS
  SELECT
    XMLElement(
      "Employee",
      XMLAttributes('http://www.oracle.com/emp_simple.xsd' AS "xmlns",
                    'http://www.w3.org/2001/XMLSchema-instance' AS "xmlns:xsi",
                    'http://www.oracle.com/emp_simple.xsd
                     http://www.oracle.com/emp_simple.xsd'
                       AS "xsi:schemaLocation"),
      XMLForest(e.employee_id     AS "EmployeeId",
                e.last_name       AS "Name",
                e.job_id          AS "Job",
                e.manager_id      AS "Manager",
                e.hire_date       AS "HireDate",
                e.salary          AS "Salary",
                e.commission_pct  AS "Commission",
                XMLForest(d.department_id    AS "DeptNo",
                          d.department_name  AS "DeptName",
                          d.location_id      AS "Location") AS "Dept"))
   FROM employees e, departments d
   WHERE e.department_id = d.department_id;

SQL関数extractValueを使用してemp_xmlから選択する問合せ

SELECT
 extractValue(OBJECT_VALUE, '/Employee/EmployeeId') AS "a1",
 extractValue(OBJECT_VALUE, '/Employee/Name') AS "b1",
 extractValue(OBJECT_VALUE, '/Employee/Job') AS "c1",
 extractValue(OBJECT_VALUE, '/Employee/Manager') AS "d1",
 extractValue(OBJECT_VALUE, '/Employee/HireDate') AS "e1",
 extractValue(OBJECT_VALUE, '/Employee/Salary') AS "f1",
 extractValue(OBJECT_VALUE, '/Employee/Commission') AS "g1"
FROM emp_xml
WHERE existsNode(OBJECT_VALUE, '/Employee/Dept[Location = 1700]') = 1;

この問合せは次のようになります。

SELECT e.employee_id a1, e.last_name b1, e.job_id c1, e.manager_id d1,
       e.hire_date e1,
       e.salary f1, e.commission_pct g1
  FROM employees e, departments d
  WHERE e.department_id = d.department_id AND d.location_id = 1700;

リライトされた問合せは、単純なリレーショナル問合せです。existsNode式のXPath述語は、ビューemp_viewで定義されているとおりに、リレーショナル列に対する述語にリライトされます。

SQL関数existsNodeを使用してemp_xmlから選択する問合せ

SELECT extractValue(OBJECT_VALUE, '/Employee/EmployeeId') as "a1",
       extractValue(OBJECT_VALUE, '/Employee/Dept/DeptNo') as "b1",
       extractValue(OBJECT_VALUE, '/Employee/Dept/DeptName') as "c1",
       extractValue(OBJECT_VALUE, '/Employee/Dept/Location') as "d1"
  FROM emp_xml
  WHERE existsNode(OBJECT_VALUE, '/Employee/Dept[Location = 1700
    AND DeptName="Finance"]') = 1;

この問合せは、XPathリライト・メカニズムを使用した単純なリレーショナル問合せにリライトされます。existsNode式のXPath述語は、ビューemp_viewで定義されているとおりに、リレーショナル列に対する述語にリライトされます。

SELECT e.employee_id a1, d.department_id b1, d.department_name c1,
       d.location_id d1
  FROM employees e, departments d
  WHERE (d.location_id = 1700 AND d.department_name = 'Finance')
    AND e.department_id = d.department_id;

オブジェクト型、オブジェクト・ビューおよびSYS_XMLGEN()を使用したビュー

次の項では、オブジェクト型、オブジェクト・ビューおよびSQL関数sys_XMLGenを使用したXMLTypeビューでのXPathリライトについて説明します。

オブジェクト型またはオブジェクト・ビューを使用したXML Schemaに基づかないXMLTypeビュー

XML Schemaに基づかないXMLTypeビューは、オブジェクト型およびオブジェクト・ビューを使用した既存のリレーショナル表およびオブジェクト・リレーショナル表に対して作成できます。これによって、ユーザーは、基礎となるデータのXMLビューを使用できます。既存のリレーショナル・データは、適切なオブジェクト型を作成し、最上位でsys_XMLGenを実行することによって、XMLTypeビューに変換できます。

例19-22 SYS_XMLGENを使用して構成されたXML Schemaに基づかないビュー

CREATE TYPE emp_t AS OBJECT (empno         NUMBER(6),
                             ename         VARCHAR2(25),
                             job           VARCHAR2(10),
                             mgr           NUMBER(6),
                             hiredate      DATE,
                             sal           NUMBER(8,2),
                             comm          NUMBER(2,2));
/

CREATE TYPE emplist_t AS TABLE OF emp_t;
/

CREATE TYPE dept_t AS OBJECT (deptno       NUMBER(4),
                              dname        VARCHAR2(30),
                              loc          NUMBER(4),
                              emps         emplist_t);
/

CREATE OR REPLACE VIEW dept_ov OF dept_t
  WITH OBJECT ID (deptno) AS
  SELECT d.department_id, d.department_name, d.location_id,
         CAST(MULTISET(
           SELECT emp_t(e.employee_id, e.last_name, e.job_id, e.manager_id,
                        e.hire_date, e.salary, e.commission_pct)
             FROM employees e
             WHERE e.department_id = d.department_id)
             AS emplist_t)
    FROM departments d;

CREATE OR REPLACE VIEW dept_xml OF XMLType
  WITH OBJECT ID (extract(OBJECT_VALUE, '/ROW/DEPTNO').getNumberVal()) AS
  SELECT sys_XMLGen(OBJECT_VALUE) FROM dept_ov;

給与が$15000を超える従業員が1人以上いる部門番号の問合せ

SELECT extractValue(OBJECT_VALUE, '/ROW/DEPTNO')
  FROM dept_xml
  WHERE existsNode(OBJECT_VALUE, '/ROW/EMPS/EMP_T[sal > 15000]') = 1;

この問合せは次のようになります。

SELECT d.department_id
  FROM departments d
  WHERE exists(SELECT NULL FROM employees e
                 WHERE e.department_id = d.department_id
                   AND e.salary > 15000);

例19-23 オブジェクト・ビューを基にSYS_XMLGENを使用して構成されたXML Schemaに基づかないビュー

たとえば、emp表内のデータを次のように公開できます。

CREATE TYPE emp_t AS OBJECT
      (empno         NUMBER(6),
       ename         VARCHAR2(25),
       job           VARCHAR2(10),
       mgr           NUMBER(6),
       hiredate      DATE,
       sal           NUMBER(8,2),
       comm          NUMBER(2,2));
/

CREATE VIEW employee_xml OF XMLType
  WITH OBJECT  ID (OBJECT_VALUE.extract('/ROW/EMPNO/text()').getnumberval()) AS
    SELECT sys_XMLGen(emp_t(e.employee_id, e.last_name, e.job_id, e.manager_id,
                            e.hire_date, e.salary, e.commission_pct))
      FROM employees e;

XML Schemaに基づかないビューの主なメリットは、DDL文を追加せずに、既存のオブジェクト・ビューを簡単にXMLTypeビューに変換できることです。たとえば、次の定義を持つオブジェクト・ビューemployee_ovを含むデータベースについて考えてみます。

CREATE VIEW employee_ov OF emp_t
  WITH OBJECT ID (empno) AS
  SELECT emp_t(e.employee_id, e.last_name, e.job_id, e.manager_id,
               e.hire_date, e.salary, e.commission_pct)
    FROM employees e;

XML Schemaに基づかないXMLTypeビューは、最上位のオブジェクト列でsys_XMLGenをコールすることにより作成できます。追加の型を作成する必要はありません。

CREATE OR REPLACE VIEW employee_ov_xml OF XMLType
  WITH OBJECT ID (OBJECT_VALUE.extract('/ROW/EMPNO/text()').getnumberval()) AS
  SELECT sys_XMLGen(OBJECT_VALUE) FROM employee_ov;

sys_XMLGenビューに対する問合せは、特定の条件を満たす場合、オブジェクト属性に直接アクセスするようにリライトされます。SQL関数existsNodeextractValueおよびextractによる単純なXPath検索は、リライトの対象になります。XPathリライトの詳細は、第7章「XPathリライト」を参照してください。たとえば、次のような問合せを発行するとします。

SELECT extract(OBJECT_VALUE, '/ROW/EMPNO')
  FROM employee_ov_xml
  WHERE extractValue(OBJECT_VALUE, '/ROW/ENAME') = 'Smith';

この問合せは次のようにリライトされます。

SELECT sys_XMLGen(e.employee_id)
  FROM employees e
  WHERE e.last_name = 'Smith';

オブジェクト型またはオブジェクト・ビューを使用したXML Schemaに基づくビュー

例19-24に、オブジェクト型を使用したXML Schemaに基づくXMLTypeビューでのXPathリライトを示します。

例19-24 オブジェクト型を使用して構成されたXML Schemaに基づくビュー

この例では、「オブジェクト・ビューからの、XML Schemaに基づくXMLTypeビューの作成」と同じオブジェクト型と同じXML Schema(emp_complex.xsd)が使用されます。

CREATE VIEW xmlv_adts OF XMLType
   XMLSchema "http://www.oracle.com/emp_complex.xsd" ELEMENT "Employee"
   WITH OBJECT OID (
          OBJECT_VALUE.extract(
            '/Employee/EmployeeId/text()').getNumberVal()) AS
          SELECT emp_t(e.employee_id, e.last_name, e.job_id, e.manager_id,
                       e.hire_date, e.salary, e.commission_pct,
                       dept_t(d.department_id, d.department_name, d.location_id))
            FROM employees e, departments d
            WHERE e.department_id = d.department_id;

SQL関数extractValueを使用する問合せ

SELECT extractValue(OBJECT_VALUE, '/Employee/EMPNO') "EmpID ",
       extractValue(OBJECT_VALUE, '/Employee/ENAME') "Ename ",
       extractValue(OBJECT_VALUE, '/Employee/JOB') "Job ",
       extractValue(OBJECT_VALUE, '/Employee/MGR') "Manager ",
       extractValue(OBJECT_VALUE, '/Employee/HIREDATE') "HireDate ",
       extractValue(OBJECT_VALUE, '/Employee/SAL') "Salary ",
       extractValue(OBJECT_VALUE, '/Employee/COMM') "Commission ",
       extractValue(OBJECT_VALUE, '/Employee/DEPT/DEPTNO') "Deptno ",
       extractValue(OBJECT_VALUE, '/Employee/DEPT/DNAME') "Deptname ",
       extractValue(OBJECT_VALUE, '/Employee/DEPT/LOC') "Location "
  FROM xmlv_adts
  WHERE existsNode(OBJECT_VALUE, '/Employee[SAL > 15000]') = 1;

この問合せは次のようになります。

SELECT e.employee_id "EmpID ", e.last_name "Ename ", e.job_id "Job ",
       e.manager_id "Manager ", e.hire_date "HireDate ", e.salary "Salary ",
       e.commission_pct "Commission ", d.department_id "Deptno ",
       d.department_name "Deptname ", d.location_id "Location "
  FROM employees e, departments d
  WHERE e.department_id = d.department_id AND e.salary > 15000;

XPathリライトのイベント・トレース

次のイベント・フラグを使用すると、SQL/XML関数を使用して構成されたビューに対するXPathリライトを使用禁止にできます。

ALTER SESSION SET EVENTS '19027 trace name context forever, level 64';

次のイベント・フラグを使用すると、オブジェクト型、オブジェクト・ビューおよびSQL関数sys_XMLGenを使用して構成されたビューに対するXPathリライトを使用禁止にできます。

ALTER SESSION SET EVENTS '19027 trace name context forever, level 1';

次のイベント・フラグを使用すると、XPathリライトが行われない理由をトレースできます。トレース・メッセージは、トレース・ファイルに出力されます。

ALTER SESSION SET EVENTS '19027 trace name context forever, level 8192';

ビューを作成せずにXML Schemaに基づくXMLを生成する方法

前述の例では、CREATE VIEW文でXML SchemaのURLおよび要素名を指定し、基礎となるビュー問合せによってXML Schemaに基づかないXMLTypeを作成しました。ただし、CREATE VIEWの手順を実行せずに、XML Schemaに基づくXMLを作成する必要がある場合もあります。

これを行うには、次のXML生成SQL関数を使用してオプションでXML SchemaのURLおよび要素名を受け入れます。

例19-25 ビューを作成せずにXML Schemaに基づくXMLを生成する方法

この例では、「ネストした従業員データを含む部門のリレーショナル・データのXMLとしてのラッピング」と同じ型とXML Schemaを使用しています。これらの定義を使用して、createXMLによってXML Schemaに基づくXMLが作成されます。

SELECT (XMLTYPE.createXML(
          dept_t(d.department_id, d.department_name, d.location_id,
              CAST(MULTISET(SELECT emp_t(e.employee_id, e.last_name, e.job_id,
               e.manager_id, e.hire_date, e.salary,
               e.commission_pct)
                          FROM employees e
                          WHERE e.department_id = d.department_id)
                      AS emplist_t)),
          'http://www.oracle.com/dept_complex.xsd', 'Department'))
  FROM departments d;

XMLTypeには自動コンストラクタがあるため、ここではXMLTYPE.createXMLXMLTYPEに置換することもできます。