ODP.NET XMLサポート
ODP.NETでは、リレーショナル表およびオブジェクト・リレーショナル表やビューからXML文書としてデータを抽出できます。XML文書の使用により、データベースへの挿入、更新および削除もできます。Oracle Databaseは、データベースでのXML、Oracle XML DBの使用、高パフォーマンスなXML記憶域および取得に関連する技術の個別のグループにネイティブに対応しています。Oracle XML DBは、データベースを発展させたものであり、相互運用方式でSQLおよびXMLデータ・モデルの両方を包含しているため、従来のXMLをサポートできます。
ODP.NET管理対象ドライバはXPath 1.0仕様に準拠しているため、デフォルトのXMLネームスペースはサポートしていません。XMLネームスペースは、検索ノードまたは更新ノードに明示的に追加する必要があります。この動作が、ODP.NET管理対象外ドライバの場合とは異なります。
Oracle Universal Installerを使用したODACインストールのODP.NET XMLサポートに関するサンプルは、次のディレクトリを参照してください。
ORACLE_BASE\ORACLE_HOME\ODACsamples
この項は次の項目で構成されています。
サポートされるXML機能
ODP.NETにおけるXMLのサポートでは、次の機能が提供されます。
-
XMLデータをそのままの形で、ネイティブなOracle Database型である
XMLType
として、データベースに格納します。 -
Oracle DatabaseインスタンスからMicrosoft .NET環境へ、XMLデータとしてリレーショナル・データおよびオブジェクト・リレーショナル・データにアクセスし、Microsoft .NET Frameworkを使用してXMLを処理します。
-
XMLデータを使用してデータベースに変更を保存します。
.NETアプリケーション開発者を対象として、これらの機能には次のものが含まれます。
-
OracleCommand
、OracleConnection
およびOracleDataReader
クラスの拡張機能。 -
次のXML固有のクラス。
-
OracleXmlType
OracleXmlType
オブジェクトは、Oracle固有のXMLType
データの取得に使用されます。 -
OracleXmlStream
OracleXmlStream
オブジェクトは、OracleXmlType
オブジェクトからXMLデータを読取り専用の.NETStream
オブジェクトとして取得する際に使用されます。 -
OracleXmlQueryProperties
OracleXmlQueryProperties
オブジェクトは、XmlCommandType
プロパティがQuery
である場合に、OracleCommand
クラスにより使用されるXMLプロパティを表します。 -
OracleXmlSaveProperties
OracleXmlSaveProperties
オブジェクトは、XmlCommandType
プロパティがInsert
、Update
またはDelete
である場合に、OracleCommand
クラスにより使用されるXMLプロパティを表します。
-
XQueryサポート
ODP.NETは、SQL/XML関数XMLQuery
とXMLTable
のネイティブ実装を通じてXQuery言語をサポートします。XQuery文を実行すると、通常Oracle XML DBはXQuery式を関連する問合せとして同じベース構造にコンパイルし値を求めます。問合せは最適化され、リレーショナル・データベースおよびXQuery固有の最適化技術の両方を活用して、Oracle XML DBはネイティブのXQueryエンジンとして動作します。すべてのXQuery式の処理は、ネイティブでコンパイルされたか、または関数的に値を求めたかにかかわらず透過的であり、プログラマはXQuery最適化の利点を活かすためにこれらのコードを変更する必要はありません。
関連項目:
OracleのXQueryサポートについてさらに学習するには、Oracle XML DB開発者ガイドを参照
OracleXmlTypeおよび接続依存性
OracleXmlType
クラスの読取り専用のConnection
プロパティは、OracleXmlType
クラスのインスタンス化に使用されるOracleConnection
オブジェクトへの参照を保持します。
OracleXmlType
オブジェクトがOracleConnection
オブジェクトへの参照を取得する方法は、OracleXmlType
クラスがインスタンス化される方法に応じて異なります。
-
GetOracleXmlType
メソッド、GetOracleValue
メソッドまたはGetOracleValues
メソッドを使用してOracleDataReader
クラスからインスタンス化された場合Connection
プロパティは、OracleDataReader
オブジェクトにより使用される同じOracleConnection
オブジェクトへの参照によって設定されます。 -
OracleConnection
型のいずれかのパラメータにより、OracleXmlType
コンストラクタを起動してインスタンス化された場合Connection
プロパティは、コンストラクタに指定された同じOracleConnection
オブジェクトへの参照によって設定されます。 -
OracleXmlType(OracleClob)
コンストラクタを起動してインスタンス化された場合Connection
プロパティは、OracleClob
オブジェクトにより使用されるOracleConnection
オブジェクトへの参照によって設定されます。
ある接続に関連付けられたOracleXmlType
オブジェクトは、別の接続に使用できません。たとえば、あるOracleXmlType
オブジェクトがOracleConnection
A
を使用して取得される場合、そのOracleXmlType
オブジェクトはOracleConnection
B
を使用するコマンドの入力パラメータとして使用できません。アプリケーションは、OracleXmlType
オブジェクトのConnection
プロパティをチェックすることで、OracleXmlType
オブジェクトが、その接続プロパティで参照されるOracleConnection
のコンテキスト内でのみ使用されることを保証できます。それ以外の場合、ODP.NETでは例外が発生します。
データベースでのXMLTypeデータの更新
XMLType
列の更新には、トランザクションは必要ありません。ただし、データベースの更新プロセス全体をトランザクション内にカプセル化することをお薦めします。これにより、エラーが発生した場合に更新をロールバックできます。
データベース内のXMLType
列をOracle Data Provider for .NETを使用して更新するには、次のように複数の方法があります。
DataSet、OracleDataAdapterおよびOracleCommandBuilderによる更新
XMLType
列がDataSet
にフェッチされた場合、XMLType
データは.NET String
として表されます。
DataSet
内のXMLType
データの変更には、特別な処理は必要ありません。XMLType
データは、DataSet
に格納されたデータと同様に変更できます。変更が加えられ、OracleDataAdapter.Update
メソッドが起動されると、OracleDataAdapter
オブジェクトにより、XMLType
データが確実に正しく処理されます。OracleDataAdapter
オブジェクトでは、提供されているカスタムSQL文のINSERT
、UPDATE
またはDELETE
が使用されます。それ以外の場合は、データベースへの変更をフラッシュする際に、必要に応じてOracleCommandBuilder
オブジェクトにより有効なSQL文が生成されます。
OracleCommandおよびOracleParameterによる更新
OracleCommand
クラスは、特にOracleParameter
オブジェクトの使用により、XMLType
データを更新するための強力な手段となります。データベース表内の列を更新するには、列の新しい値をコマンドの入力パラメータとして渡すことができます。
入力バインド
データベース内のXMLType
列を更新するには、静的な値を使用してSQL文を実行できます。さらに、入力パラメータをSQL文、無名PL/SQLブロックまたはストアド・プロシージャにバインドし、XMLType
列を更新できます。パラメータ値は、.NET Frameworkタイプ、ODP.NETタイプまたはOracleXmlType
オブジェクトとして設定できます。
XMLType
列はOracleXmlType
オブジェクトを使用して更新できますが、OracleXmlType
クラスのインスタンスを保持していても、データベース内のXMLType
列を更新できることが保証されるわけではありません。
XMLType列のNULL値への設定
アプリケーションでは、次のように入力バインドを使用する方法または使用しない方法で、データベース内のXMLType
列をNULL
値に設定できます。
-
入力バインドによる
XMLType
列内のNULL
値の設定XMLType
列をNULL
に設定するには、アプリケーションにより、値がDBNull
.Value
である入力パラメータをバインドできます。これによって、OracleCommand
オブジェクトに対し、NULL
値が挿入されることが示されます。NULLの
OracleXmlType
オブジェクトを入力パラメータとして渡した場合、XMLType
列にNULL
が挿入されません。この場合、OracleCommand
オブジェクトでは例外が発生します。 -
入力バインドを使用しない
XMLType
列内のNULL
値の設定次の例では、入力バインドを使用せずに
XMLType
列でNULL
値を設定する方法を示しています。// Create a table with an XMLType column in the database CREATE TABLE XML_TABLE(NUM_COL number, XMLTYPE_COL xmltype);
アプリケーションでは、明示的に
NULL
値を挿入するか、または次の例のようにXMLType
列になにも挿入しないことで、この列にNULL
値を設定できます。insert into xml_table(xmltype_col) values(NULL);
update xml_table t set t.xmltype_col=NULL;
OracleXmlTypeでのXMLデータの更新
OracleXmlType
オブジェクトでXMLデータを更新するには、複数の方法があります。
-
OracleXmlType
オブジェクトのUpdate
メソッドにXPATH式および新しい値を渡すことで、XMLデータを更新できます。 -
XMLデータは、
OracleXmlType
オブジェクトのGetXmlDocument
メソッドを使用して、.NET FrameworkのXmlDocument
オブジェクトとしてクライアント側で取得できます。このため、このXMLデータは適切な.NET Frameworkクラスを使用して操作できます。.NET Frameworkクラスから、更新されたXMLデータにより新規のOracleXmlType
を作成できます。この新規のOracleXmlType
は、入力パラメータとしてUPDATE文またはINSERT文にバインドされます。
XMLの特殊文字
表3-21の次の文字は、XMLでは特殊な意味を持ちます。詳細は、XML 1.0の仕様を参照してください。
表3-21 XMLの特殊文字
特殊文字 | XMLでの意味 | 実体エンコード |
---|---|---|
< |
XMLタグの開始 |
< |
> |
XMLタグの終了 |
> |
" |
引用符 |
" |
' |
アポストロフィまたは一重引用符 |
' |
& |
アンパサンド |
& |
これらの文字がXML要素内のデータとして使用されている場合、対応する実体エンコードに置き換えられます。
また、XML要素名では特定の文字が無効です。SQL識別子(列名など)がXML要素名にマップされている場合、これらの文字は、Unicodeの文字エンコードから導出された一連の16進数字に変換され、前置きのアンダースコア、小文字のx
および後続のアンダースコアで囲まれます。空白はXML要素名では有効な文字ではありません。SQL識別子に空白文字が含まれる場合、対応するXML要素名において、空白文字が_x0020_
に置き換えられます。これは、空白文字のUnicodeエンコードに基づいています。
問合せの結果セットのXML形式での取得
この項では、SQL問合せから結果セットをXMLデータ形式で取得する方法について説明します。
日時書式の処理
生成されたXMLのDATE
およびTIMESTAMP
書式は、標準のXML Schema書式を基にしています。
関連項目:
XML Schema仕様の詳細は、http://www.w3.org/TR/2004/REC-xmlschema-2-20041028/datatypes.html#isoformats
を参照してください。
列データの特殊文字
問合せ内の選択リスト列のいずれかにあるデータに、XMLの特殊文字が含まれている場合(表3-21を参照)、結果であるXML文書では、これらの文字は対応する実体エンコードに置き換えられます。
次の例では、ODP.NETで列データ内の山カッコの特殊文字が処理される方法を示しています。
/* Database Setup connect scott/tiger@oracle drop table specialchars; create table specialchars ("id" number, name varchar2(255)); insert into specialchars values (1, '<Jones>'); commit; */ // C# using System; using System.Data; using System.Xml; using Oracle.DataAccess.Client; class QueryResultAsXMLSample { static void Main() { OracleConnection con = new OracleConnection(); con.ConnectionString = "User Id=scott;Password=tiger;Data Source=oracle;"; con.Open(); // Create the command OracleCommand cmd = new OracleCommand("", con); // Set the XML command type to query. cmd.XmlCommandType = OracleXmlCommandType.Query; // Set the SQL query cmd.CommandText = "select * from specialchars"; // Set command properties that affect XML query behavior. cmd.BindByName = true; // Set the XML query properties cmd.XmlQueryProperties.MaxRows = -1; // Get the XML document as an XmlReader. XmlReader xmlReader = cmd.ExecuteXmlReader(); XmlDocument xmlDocument = new XmlDocument(); xmlDocument.PreserveWhitespace = true; xmlDocument.Load(xmlReader); Console.WriteLine(xmlDocument.OuterXml); // Close and Dispose OracleConnection object con.Close(); con.Dispose(); } }
この表に対して次のXML文書が生成されます。山カッコを表すXML実体エンコードは太字で表記されます。
<?xml version = '1.0'?> <ROWSET> <ROW> <id>1</id > <NAME><Jones></NAME> </ROW> </ROWSET>
表名またはビュー名の特殊文字
表名またはビュー名に英数字以外の文字(アンダースコア(_)を除く)が含まれる場合、この表名またはビュー名は引用符で囲む必要があります。
たとえば、名前がtest'ing
の表からすべてのエントリを選択するには、OracleCommand
オブジェクトのCommandText
プロパティを次の文字列に設定する必要があります。
"select * from \"test'ing\"";
列名とXML要素名のマッピングにおける大/小文字区別
SQL識別子(列名)とXML要素名のマッピングは大/小文字が区別され、要素名は表またはビューの列名と大/小文字がまったく同じになります。
ただし、ルート・タグ名および行タグ名は大/小文字が区別されません。次の例では、この場合の大/小文字区別を示しています。
//Create the following table create table casesensitive_table ("Id" number, NAME varchar2(255)); //insert name and id insert into casesensitive_table values(1, 'Smith');
次のXML文書が生成されます。
<?xml version = '1.0'?> <ROWSET> <ROW> <Id>1</Id> <NAME>Smith</NAME> </ROW> </ROWSET>
Id
列の要素名の大/小文字が列名と一致する点に注意してください。
列名とXML要素名のマッピング
SQL問合せにより生成された行ごとに、SQL識別子(列名)が、生成されたXML文書内のXML要素にマップされます。
// Create the following table create table emp_table (EMPLOYEE_ID NUMBER(4), LAST_NAME varchar2(25)); // Insert some data insert into emp_table values(205, 'Higgins');
SELECT
*
FROM
EMP_TABLE
というSQL問合せにより、次のXML文書が生成されます。
<?XML version="1.0"?> <ROWSET> <ROW> <EMPLOYEE_ID>205</EMPLOYEE_ID> <LAST_NAME>Higgins</LAST_NAME> </ROW> </ROWSET>
employees
表のEMPLOYEE_ID
およびLAST_NAME
データベース列は、生成されたXML文書のEMPLOYEE_ID
要素およびLAST_NAME
要素にマップされます。
この項では、データベースからXMLとして問合せ結果を取得する場合に、Oracle DatabaseでSQL識別子のXML要素名へのマッピングを処理する方法について説明します。デモでは、some
id
列を含むspecialchars
表を使用します。
// Create the specialchars table create table specialchars ("some
id
" number, name varchar2(255));
specialchars
表には、空白文字が含まれるsome
id
列がある点に注意してください。XML要素名では、空白文字は使用できません。
問合せ結果をXMLで取得する場合、問合せの選択リスト内のSQL識別子には、XML要素名で無効となる文字を使用できます。これらのSQL識別子(列名など)がXML要素名にマップされている場合、これらの各文字は、Unicodeの文字エンコードから導出された一連の16進数字に変換され、前置きのアンダースコア、小文字のxおよび後続のアンダースコアで囲まれます。
このため、次の例のSQL問合せを使用して、specialchars
表から結果をXML文書で取得できます。
select "some id", name from specialchars;
関連項目:
デフォルト・マッピングの修正
次の方法でXML要素名へのSQL識別子のデフォルト・マッピングを修正できます。
-
ソースを変更します。ソース・スキーマ上にオブジェクト・リレーショナル・ビューを作成し、このビューを新規ソースにします。
-
SQL問合せでカーソル副問合せおよびキャスト多重集合構造を使用します。
-
SQL問合せで列名または属性名の別名を作成します。別名にアットマーク(@)を付加し、別名をXML要素ではなくXML属性にマップします。
-
XML文書を変更します。Extensible Stylesheet Language Transformation(XSLT)を使用してXML文書を変換します。XSL文書およびパラメータを指定します。リレーショナル・データからXML文書が生成された後、変換が自動的に実行されます。これはパフォーマンスに影響する可能性があります。
-
XML文書で使用されるルート・タグおよび行タグの名前を指定します。
オブジェクト・リレーショナル・データ
ODP.NETでは、オブジェクト・リレーショナル列、表およびビューに格納されたデータについて、XML文書を生成できます。
// Create the following tables and types CREATE TYPE "EmployeeType" AS OBJECT (EMPNO NUMBER, ENAME VARCHAR2(20)); / CREATE TYPE EmployeeListType AS TABLE OF "EmployeeType"; / CREATE TABLE mydept (DEPTNO NUMBER, DEPTNAME VARCHAR2(20), EMPLIST EmployeeListType) NESTED TABLE EMPLIST STORE AS EMPLIST_TABLE; INSERT INTO mydept VALUES (1, 'depta', EmployeeListType("EmployeeType"(1, 'empa')));
この表に対して次のXML文書が生成されます。
<?xml version = "1.0"?> <ROWSET> <ROW> <DEPTNO>1</DEPTNO> <DEPTNAME>depta</DEPTNAME> <EMPLIST> <EmployeeType> <EMPNO>1</EMPNO> <ENAME>empa</ENAME> </EmployeeType> </EMPLIST> </ROW> </ROWSET>
ODP.NETでは、コレクション要素内の各項目が、コレクション内の要素のデータベース型名で囲まれます。mydept
表にはEMPLIST
データベース列にコレクションがあり、このコレクション内の各項目はEmployeeType
型です。このため、XML文書では、例に太字で表されるように、コレクション内の各項目が型名EmployeeType
で囲まれます。
XMLを使用したデータ操作
この項では、XMLを使用してデータベースのデータに変更を加える方法について説明します。
日時書式の処理
生成されたXMLのDATE
およびTIMESTAMP
書式は、標準のXML Schema書式を基にしています。
関連項目:
XML Schema仕様の詳細は、http://www.w3.org/TR/2004/REC-xmlschema-2-20041028/datatypes.html#isoformats
を参照してください。
XMLを使用した変更の保存
XMLデータを使用して、データベース表およびビューに変更を保存できます。ただし、挿入、更新および削除の操作は、単一のXML文書では組み合せることができません。ODP.NETでは、単一のXML文書を受け入れて、どの変更が挿入、更新または削除のいずれであるかを判別できません。
挿入変更では挿入する行、更新変更では更新する行、削除変更では削除する行のみが含まれるXML文書である必要があります。
たとえば、HRサンプル・スキーマに付属するemployees
表を使用して、次の問合せを指定できます。
select employee_id, last_name from employees where employee_id = 205;
次のXML文書が生成されます。
<?xml version = '1.0'?>
<ROWSET>
<ROW>
<EMPLOYEE_ID>205</EMPLOYEE_ID>
<LAST_NAME>Higgins</LAST_NAME>
</ROW>
</ROWSET>
従業員205
の名前をHiggins
からSmith
に変更するには、employees
表および変更が含まれるXMLデータを次のように指定します。
<?xml version = '1.0'?>
<ROWSET>
<ROW>
<EMPLOYEE_ID>205</EMPLOYEE_ID>
<LAST_NAME>Smith</LAST_NAME>
</ROW>
</ROWSET>
列データの特殊文字
XML文書内のいずれかの要素内のデータに、XMLの特殊文字が含まれている場合(表3-21を参照)、そのデータがデータベース表列に正しく格納されるためには、XML文書で、これらの文字を適切な実体エンコードに置き換えるか、エスケープ文字で上書きする必要があります。そうしないと、ODP.NETは例外をスローします。
次の例では、ODP.NETで実体エンコードを使用して列データ内の山カッコの特殊文字が処理される方法を示しています。
// Create the following table create table specialchars ("id" number, name varchar2(255));
次のXML文書を使用して、値(1,
、'<Jones>')
をspecialchars
表に挿入できます。山カッコを表すXML実体エンコードは太字で表記されます。
<?xml version = '1.0'?> <ROWSET> <ROW> <id>1</id > <NAME><Jones></NAME> </ROW> </ROWSET>
表名またはビュー名の特殊文字
表名またはビュー名に英数字以外の文字(アンダースコア(_)を除く)が含まれる場合、この表名またはビュー名は引用符で囲む必要があります。
たとえば、名前がtest'ing
の表に変更を保存するには、OracleCommand.XmlSaveProperties.TableName
プロパティを"\"test'ing\""
に設定する必要があります。
XML要素名と列名のマッピングにおける大/小文字区別
XML文書内のデータ行を表すXML要素ごとに、子XML要素がデータベース列名にマップされます。子要素名と列名のマッピングでは常に大/小文字が区別されますが、ルート・タグ名および行タグ名では区別されません。この大/小文字区別の例を次に示します。
//Create the following table create table casesensitive_table ("Id" number, NAME varchar2(255));
次のXML文書を使用して、値(1
、Smith
)をcasesensitive_table
に挿入できます。
<?xml version = '1.0'?> <ROWSET> <ROW> <Id>1</Id> <NAME>Smith</NAME> </ROW> </ROWSET>
Id
列の要素名の大/小文字が列名と一致する点に注意してください。
XML要素名と列名のマッピング
この項では、データベースでデータ操作にXMLを使用する場合に、Oracle Databaseで列名へのXML要素名のマッピングを処理する方法について説明します。次にsome
id
列を含むspecialchars
表を使用する処理を示します。
// Create the specialchars table create table specialchars ("some
id
" number, name varchar2(255));
specialchars
表には、空白文字が含まれるsome
id
列がある点に注意してください。XML要素名では、空白文字は使用できません。
XML文書を使用した表への変更の保存
XML文書を使用して表またはビューに変更を保存する場合、OracleCommand.XmlSaveProperties.UpdateColumnsList
を使用して、更新または挿入する列のリストを指定します。
XML文書を使用して表またはビュー内の列の変更を保存する場合で、対応する列名にXML要素名では無効となる文字が含まれる場合、次の例のように、UpdateColumnsList
プロパティにエスケープした列名を指定する必要があります。
次のXML文書を使用して、値(2
、<Jones>
)をspecialchars
表に挿入できます。
<?xml version = '1.0'?> <ROWSET> <ROW> <some_x0020_id>2</some_x0020_id> <NAME><Jones></NAME> </ROW> </ROWSET>
次のコード例は、更新または挿入する列のリストを指定します。
/* Database Setup connect scott/tiger@oracle drop table specialchars; create table specialchars ("some id" number, name varchar2(255)); insert into specialchars values (1, '<Jones>'); commit; */ // C# using System; using System.Data; using System.Xml; using Oracle.DataAccess.Client; class InsertUsingXmlDocSample { static void Main() { OracleConnection con = new OracleConnection(); con.ConnectionString = "User Id=scott;Password=tiger;Data Source=oracle;"; con.Open(); Console.WriteLine("Connected Successfully"); // Create the command OracleCommand cmd = new OracleCommand("", con); // Set the XML command type to query. cmd.XmlCommandType = OracleXmlCommandType.Insert; // Set the XML document cmd.CommandText = "<?xml version = '1.0'?>\n" + "<ROWSET>\n" + "<ROW>\n" + "<some_x0020_id>2</some_x0020_id>\n" + "<NAME><Jones></NAME>\n" + "</ROW>\n" + "</ROWSET>\n"; cmd.XmlSaveProperties.Table = "specialchars"; string[] ucols = new string[2]; ucols[0] = "some_x0020_id"; ucols[1] = "NAME"; cmd.XmlSaveProperties.UpdateColumnsList = ucols; // Insert rows int rows = cmd.ExecuteNonQuery(); Console.WriteLine("Number of rows inserted successfully : {0} ", rows); // Close and Dispose OracleConnection object con.Close(); con.Dispose(); } }
オブジェクト・リレーショナル・データ
XML文書の変更は、オブジェクト・リレーショナル・データにも保存できます。コレクション内の各項目は、XML文書に次のいずれかの方法で指定できます。
-
項目のデータベース型名をXML要素名として囲みます。
-
_ITEM
がXML要素名として追加されたコレクションを保持するデータベース列名を囲みます。
複数の表
Oracle Databaseでは、結合された複数のリレーショナル表への変更は保存しません。リレーショナル表に対するビューを作成してから、そのビューを更新することをお薦めします。ビューが更新可能でない場合は、かわりにトリガーを使用できます。
関連項目:
CREATE
VIEW
文の説明と構文は、『Oracle Database SQL言語リファレンス』を参照