この章では、XMLType
ビューを作成および使用する方法を説明します。
この章の内容は次のとおりです。
XMLType
ビューは、既存のリレーショナル・データおよびオブジェクト・リレーショナル・データをXML形式でラップします。XMLType
ビューを使用する主なメリットは次のとおりです。
基本のレガシー・データを移行せずに、XML Schema機能を使用するOracle XML DBのXML機能を使用できます。
XMLType
ビューでは、XMLType
表で使用可能なオブジェクト・リレーショナル記憶域、CLOB
記憶域、バイナリXML記憶域の他に、様々な形式の記憶域を使用できます。
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つのタイプがあります。
XML Schemaに基づくXMLTypeビュー。XMLType
表に関して、特定のXML Schemaに準拠するXMLType
ビューは、XML Schemaに基づくXMLType
ビューといいます。これらのビューでは、XML Schemaに基づかないXMLType
ビューより厳密な型指定ができます。
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
ビューは、次の方法で構成できます。
XMLElement
、XMLForest
、XMLConcat
、XMLAgg
およびOracle Databaseの拡張関数XMLColAttVal
などのSQL/XML生成関数に基づいて構成する方法。SQL/XML生成関数を使用すると、XML Schemaに基づかないXMLType
ビューとXML Schemaに基づくXMLType
ビューの両方を構成できます。これによって、リレーショナル・レガシー・データをXMLに物理的に移行せずに、基礎となるリレーショナル表から直接XMLType
ビューを構成できます。ただし、XML Schemaに基づくXMLType
ビューを構成するには、XML Schemaを登録する必要があり、SQL/XML関数によって生成されたXML値はXML Schemaに制限される必要があります。
オブジェクト型、オブジェクト・ビューおよびSQL関数sys_XMLGen
に基づいて構成する方法。XML Schemaに基づかないXMLType
ビューは、オブジェクト型、オブジェクト・ビューおよび関数sys_XMLGen
を使用して構成できます。XML Schemaに基づくXMLType
ビューは、オブジェクト型およびオブジェクト・ビューを使用して構成できます。これによって、リレーショナルまたはオブジェクト・リレーショナルのレガシー・データをXMLに物理的に移行せずに、基礎となるリレーショナル表またはオブジェクト・リレーショナル表から直接XMLType
ビューを構成できます。XML Schemaに基づかないXMLType
ビューの作成では、既存のオブジェクト型またはオブジェクト・ビューに対してsys_XMLGen
を使用する必要があります。XML Schemaに基づくXMLType
ビューでは、既存のオブジェクト型へのマッピングをXML Schemaに注釈として付けるか、または既存のオブジェクト型からXML Schemaを生成する必要があります。
XML Schemaに基づくXMLType
ビューは、XMLType
表から直接構成することもできます。
図19-1に、XMLType
ビューを作成するためのCREATE VIEW
句を示します。CREATE VIEW
の構文の詳細は、『Oracle Database SQL言語リファレンス』を参照してください。
XML Schemaに基づかないXMLType
ビューでは、結果として戻されるXML値が、登録されたXML Schema内の特定の要素に制限されません。XML Schemaに基づかないXMLType
を作成するには、主に2つの方法があります。
XMLElement
、XMLForest
、XMLConcat
、XMLAgg
およびXMLColAttVal
などのSQL/XML生成関数を使用する方法。この方法では、オブジェクト型を作成せずに、単純なSQL/XML生成関数を使用してXMLType
ビューを作成します。SQL/XML関数を使用したXMLType
ビューの作成は、オブジェクト型またはオブジェクト・ビューを作成する必要がないため簡単です。
SQL関数sys_XMLGen
でオブジェクト型およびオブジェクト・ビューを使用する方法。この方法では、sys_XMLGen
でオブジェクト型を使用してXMLType
ビューを作成します。このXMLType
ビューを作成する方法は、すでにオブジェクト型、ビューおよび表などのオブジェクト・リレーショナル・スキーマが存在し、そのスキーマをXML Schemaを作成せずに直接XMLにマップする場合に便利です。
例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/@empno
はempno
列を直接参照できます。
リレーショナル表またはリレーショナル・ビュー内の既存のデータは、このメカニズムを使用してXMLとして公開できます。ビューがSQL/XML生成関数によって生成されると、XPath式を使用してそのビューにアクセスする問合せは、多くの場合、最適化されます(リライトされます)。最適化された問合せは、基礎となるリレーショナル列に直接アクセスできます。「XMLTypeビューでのXPathリライト」を参照してください。
これらのXMLType
ビューに対してDML操作を行うことができますが、通常、DML操作を処理するためにINSTEAD OFトリガーを作成する必要があります。
オブジェクト型を指定した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関数extract
、extractValue
、およびexistsNode
を使用した、sys_XMLGen
によって生成されたビューへの問合せは、XPathリライトの対象になります。XPathリライトは、基礎となるオブジェクト属性またはリレーショナル列への直接アクセスを容易にします。
XML Schemaに基づくXMLType
ビューでは、結果として戻されるXML値が、登録されたXML Schema内の特定の要素に制限されます。XML Schemaに基づくXMLType
を作成するには、主に2つの方法があります。
XMLElement
、XMLForest
、XMLConcat
、XMLAgg
およびXMLColAttVal
などのSQL/XML生成関数を使用する方法。ここでは、単純なSQL/XML生成関数を使用してXMLType
ビューを作成します。オブジェクト型を作成する必要はありません。このメカニズムは、オブジェクト型またはオブジェクト・ビューを作成する必要がないため簡単です。
オブジェクト型またはオブジェクト・ビュー(あるいはその両方)を使用する方法。この方法では、オブジェクト型またはオブジェクト・ビューを使用して、XMLType
ビューを作成します。このXMLType
ビューを作成するメカニズムは、すでにオブジェクト・リレーショナル・スキーマが存在し、そのスキーマを直接XMLにマップする場合に便利です。
SQL/XML生成関数を使用すると、「XML Schemaに基づかないXMLTypeビューの作成」の項で説明したXML Schemaに基づかない場合と同様の方法で、XML Schemaに基づくXMLType
ビューを作成できます。XML Schemaに基づくXMLType
ビューを作成するには、次の手順を実行します。
必要なXML構造を含むXML Schema文書を作成および登録します。XMLType
ビューはSQL/XML生成関数を使用して構成されているため、XMLとSQLオブジェクト型間のマッピングを表す注釈をXML Schemaに付ける必要がないことに注意してください。
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では、XMLElement
はEmployee
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>
複数の名前空間を含む複合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を含むリレーショナル・データまたはオブジェクト・リレーショナル・データをラップするには、オブジェクト・ビューを使用して、次の手順を実行します。
オブジェクト型を作成します。
XML構造を含むXML Schema文書を作成(または生成)し、SQLオブジェクト型および属性へのマッピングとともに登録します。XML Schemaは既存のオブジェクト型から生成でき、XMLとオブジェクト型との間のマッピングが含まれるように注釈を付ける必要があります。
XML Schemaを登録する前に、オプションのOracle XML DB属性を指定できます。この場合、Oracleによって追加情報が検証され、Oracle XML DB属性に指定した値が他のXML Schema宣言と互換性があるかどうかが確認されます。この形式のXML Schema登録は、通常、XMLType
ビューを使用して既存のデータをラップするときに行われます。
PL/SQL関数DBMS_XMLSchema.generateSchema
およびDBMS_XMLSchema.generateSchemas
を使用して、指定したオブジェクト型に対するデフォルトのXMLマッピングを生成できます。生成されたXML Schema文書には、SQLType
、SQLSchema
などの属性が指定されています。その後、これらのXML Schema文書を登録すると、次の検証フォームが生成されます。
simpleTypeに基づく属性または要素に対するSQLType:これは、対応するXMLType
と互換性があります。たとえば、XML文字列のデータ型は、VARCHAR2
またはラージ・オブジェクト(LOB)データ型にのみマップされます。
complexTypeに基づく要素に対して指定されたSQLType:これは、LOBまたはcomplexType
の宣言と互換性がある構造を持つオブジェクト型のいずれかです。オブジェクト型には、正しいデータ型を持つ正しい数の属性が含まれます。
XMLType
ビューを作成し、XML SchemaのURLおよびルート要素名を指定します。基礎となるビュー問合せによって、まずオブジェクト・インスタンスが作成され、これらのインスタンスがXMLに変換されます。この手順は、次の2つの手順でも実行できます。
オブジェクト・ビューを作成します。
そのオブジェクト・ビューのXMLType
ビューを作成します。
たとえば、従業員と部門のリレーショナル表、およびこのデータのXMLビューに基づく次の項を見てみます。
1つ目の例では、手順1から手順4bまでを実行して、ネストした部門情報を含む従業員のリレーショナル・データをXMLとしてラップします。
例19-8は、ビューに対応するオブジェクト型を作成しています。
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のリストを生成します。
XML Schema emp_complex.xsd
は、XML要素および属性を、オブジェクト型の対応する属性にマップする方法も指定します。例19-10は、XML Schema emp_complex.xsd
の登録方法を示しています。例19-10のxdb: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"
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
を使用することをお薦めします。
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;
2つ目の例では、手順1から手順3bまでを実行して、ネストした従業員情報を含む部門のリレーショナル・データをXMLとしてラップします。
最初の手順は、必要な型の作成です。例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); /
既存の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; /
次の手順は部門オブジェクト型からの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;
オブジェクト型の定義を使用せずに、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が任意で作成される可能性があるためです。 |
たとえば、いくつかの述語を使用して、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
ビューを作成する方法を示しています。
XMLType
ビュー・オブジェクトは、SQL関数ref
を使用して参照できます。
SELECT ref(d) FROM dept_xml_tab d;
XMLType
ビュー参照は、次のいずれかのオブジェクトIDに基づきます。
システム生成OID: XMLType
表のビューまたはオブジェクト・ビュー
主キー・ベースのOID: OBJECT ID
式を持つビュー
これらのREF
は、OCIオブジェクト・キャッシュ内のOCIXMLType
インスタンスをフェッチするために使用できます。また、SQL問合せ内でも使用できます。これらのREF
は、オブジェクト・ビューへのREF
と同様に動作します。
本来、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;
オブジェクト型、オブジェクト・ビューまたはSQL関数sys_XMLGen
を使用して構成されたXMLType
ビューでのXPathリライトは、通常のXMLType
表の列のXPathリライトと同じです。したがって、ビュー列に対するSQL関数extract
、existsNode
、およびextractValue
は、パフォーマンスを向上させるために、基礎となるリレーショナル・アクセスまたはオブジェクト・リレーショナル・アクセスにリライトされます。
SQL/XMLを使用して構成されたXMLType
ビューでのXPathリライトもサポートされています。ビュー列に対する関数extract
、existsNode
、およびextractValue
は、パフォーマンスを向上させるために、基礎となるリレーショナル・アクセスにリライトされます。
この項では、SQL/XML関数を使用して構成されたXMLType
ビューのXML Schemaに基づくXPathリライトおよび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 式が使用されます。 |
例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;
次の項では、オブジェクト型、オブジェクト・ビューおよびSQL関数sys_XMLGen
を使用したXMLType
ビューでのXPathリライトについて説明します。
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関数existsNode
、extractValue
および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';
例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;
次のイベント・フラグを使用すると、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';
前述の例では、CREATE VIEW
文でXML SchemaのURLおよび要素名を指定し、基礎となるビュー問合せによってXML Schemaに基づかないXMLType
を作成しました。ただし、CREATE VIEW
の手順を実行せずに、XML Schemaに基づくXMLを作成する必要がある場合もあります。
これを行うには、次のXML生成SQL関数を使用してオプションでXML SchemaのURLおよび要素名を受け入れます。
createXML
sys_XMLGen
sys_XMLAgg
例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.createXML
をXMLTYPE
に置換することもできます。