1 RDFセマンティク・グラフの概要

セマンティク・テクノロジに対するOracle Spatial and Graphのサポートは、主にResource Description Framework (RDF)およびWeb Ontology Language (OWL)のサブセットで構成されています。これらの機能は、Oracle Spatial and GraphのRDFセマンティク・グラフ機能と呼ばれます。

この章では、読者がRDFおよびOWLに関する主要な概念({主語、述語、目的語}のトリプル、URI、空白ノード、プレーン・リテラル、型付きリテラル、オントロジなど)についてよく理解していることを前提とします。こうした概念の詳細は説明しないかわりに、各概念がどのようにOracleに実装されているかを重点的に解説します。

セマンティク・データを操作するためのPL/SQLサブプログラムは、SEM_APISパッケージに含まれています。詳細は、「SEM_APISパッケージのサブプログラム」を参照してください。

RDFサポートおよびOWLサポートは、Oracle Spatial and Graphの機能です。これらの機能を使用するには、Oracle Spatial and Graphをインストールする必要があります。ただし、RDFおよびOWLの使用は、空間データに制限されません。

注意:

リリース12.2よりも前のOracle Databaseで作成されたセマンティク・データがある場合は、「リリース12.2よりも前のセマンティク・データに必要な移行作業」を参照してください。

OWLの概念とOracle DatabaseによるOWL機能のサポートの詳細は、「OWLの概要」を参照してください。

注意:

このマニュアルで説明している操作を実行するには、「RDFセマンティク・グラフ・サポートを有効にする」に示すように、前もってデータベースでRDFセマンティク・グラフ・サポートを有効にして他の前提条件も満たす必要があります。

1.1 Oracleセマンティク・テクノロジ・サポートの概要

Oracle Databaseでは、セマンティク・データとオントロジを格納し、セマンティク・データを問い合せることや、エンタープライズ・リレーショナル・データに対してオントロジ支援問合せを実行することができ、また、付属の推論またはユーザー定義の推論を使用して、セマンティク・データに対する問合せ機能を拡張することも可能です。

図1-1に、これらの機能の相互関係を示します。

図1-1 Oracleのセマンティク機能

図1-1の説明が続きます
「図1-1 Oracleのセマンティク機能」の説明

図1-1に示されているとおり、データベースには、セマンティク・データおよびオントロジ(RDF/OWLモデル)に加え、従来のリレーショナル・データが含まれます。セマンティク・データをロードするには、バルク・ロードが最も効率的な方法ですが、トランザクション型のINSERT文を使用してデータを増分ロードすることも可能です。

注意:

Oracle Databaseリリース11.1より前のリリースで作成した既存のセマンティク・データを使用する場合、「RDFセマンティク・グラフ・サポートの有効化」の手順に従ってデータをアップグレードする必要があります。

セマンティク・データおよびオントロジは問合せ可能です。また、セマンティク・データや従来のリレーショナル・データに対してオントロジ支援問合せを実行し、セマンティク関係を検出することもできます。オントロジ支援型問合せを実行するには、SEM_RELATED演算子を使用します(「リレーショナル・データに対する照会でのセマンティク演算子の使用」を参照)。

セマンティク・データに対する問合せ機能は、推論を使用して拡張できます。推論では、ルールベースのルールを使用します。推論により、データおよびルールに基づいて論理的な推測を行うことができます。推論でルールおよびルールベースを使用する方法の詳細は、「推論: ルールとルールベース」を参照してください。

1.2 セマンティク・データのモデル化

セマンティク・データには、その形式意味論に加え、有向グラフを使用して効率的にモデル化される単純なデータ構造が含まれます。

メタデータ文は、トリプルとして表現されます。ノードはトリプルの2つの部分を示すために使用され、3番目の部分はノード間の関係を記述する有向リンクによって示されます。トリプルは、セマンティク・データ・ネットワークに格納されます。また、データベース・ユーザーにより作成された特定のセマンティク・データ・モデルに関する情報も保持されます。ユーザーにより作成されたモデルは、モデル名を持ち、指定した表の列に格納されているトリプルを参照します。

文は、{主語(リソース)、述語(プロパティ)、目的語(値)}のトリプルで表現されます。このマニュアルでは、{主語、プロパティ、目的語}を使用してトリプルを記述し、という用語とトリプルという用語は、同義的に使用される場合があります。各トリプルは、特定のドメインに関する完全で一意のファクトであり、有向グラフのリンクで表現されます。

1.3 データベースのセマンティク・データ

データベースに格納されるすべてのセマンティク・データに対して、単一の場所が用意されます。

すべてのトリプルは、解析され、MDSYSスキーマの表内のエントリとしてシステムに格納されます。{主語、プロパティ、目的語}のトリプルは、1つのデータベース・オブジェクトとして処理されます。そのため、複数のトリプルを含む単一の文書は、複数のデータベース・オブジェクトになります。

トリプルのすべての主語および目的語は、セマンティク・データ・ネットワークのノードにマップされます。プロパティは、主語を開始ノード、目的語を終了ノードとするネットワーク・リンクにマップされます。使用可能なノード・タイプは、空白ノード、URI、プレーン・リテラルおよび型付きリテラルです。

URIの指定とデータベースへのセマンティク・データの格納には、次の要件が適用されます。

  • 主語は、URIまたは空白ノードである必要があります。

  • プロパティは、URIである必要があります。

  • 目的語は、URI、空白ノードまたはリテラルのいずれのタイプでもかまいません。(ただし、NULL値およびNULL文字列はサポートされません。)

1.3.1 モデルのメタデータ

MDSYS.SEM_MODEL$ビューには、データベースで定義されているすべてのモデルの情報が含まれます。SEM_APIS.CREATE_SEM_MODELプロシージャを使用してモデルを作成する場合、モデルの名前と、セマンティク・データへの参照を保持する表および列を指定します。システムにより、モデルIDが自動的に生成されます。

Oracleでは、モデルの作成および削除に応じてMDSYS.SEM_MODEL$ビューが自動的に管理されます。ユーザーがこのビューを直接変更することはできません。たとえば、このビューでSQLのINSERT、UPDATEまたはDELETE文を使用することはできません。

表1-1に、MDSYS.SEM_MODEL$ビューの列を示します。

表1-1 MDSYS.SEM_MODEL$ビューの列

列名 データ型 説明

OWNER

VARCHAR2(30)

モデルの所有者のスキーマ。

MODEL_ID

NUMBER

一意のモデルID番号(自動生成)。

MODEL_NAME

VARCHAR2(25)

モデルの名前。

TABLE_NAME

VARCHAR2(30)

モデルのセマンティク・データへの参照を保持する表の名前。

COLUMN_NAME

VARCHAR2(30)

モデルのセマンティク・データへの参照を保持する表に含まれるSDO_RDF_TRIPLE_S型の列の名前。

MODEL_TABLESPACE_NAME

VARCHAR2(30)

このモデルのトリプルを格納するための表領域の名前。

MODEL_TYPE

VARCHAR2(40)

値はRDFモデルのタイプを示し、Mは通常のモデル、Vは仮想モデル、Xはセマンティク索引の内容の格納用に作成されたモデル、Dはリレーショナル・データで作成されたモデルを示します。

モデルを作成すると、そのモデルに関連付けられたトリプルのビューもMDSYSスキーマに作成されます。このビューは、SEMM_model-nameという形式の名前を持ち、モデルの所有者および適切な権限を持つユーザーにのみ表示されます。各MDSYS.SEMM_model-nameビューには、ネットワークにリンクとして格納されたトリプルごとに1つの行が保持されます。表1-2に、このビューの列を示します。

表1-2 MDSYS.SEMM_model-nameビューの列

列名 データ型 説明

P_VALUE_ID

NUMBER

トリプルの述語のテキスト値に対応するVALUE_ID。主キーの一部です。

START_NODE_ID

NUMBER

トリプルの主語のテキスト値に対応するVALUE_ID。主キーの一部です。

CANON_END_NODE_ID

NUMBER

トリプルの目的語の正規形のテキスト値に対応するVALUE_ID。主キーの一部です。

END_NODE_ID

NUMBER

トリプルの目的語のテキスト値に対応するVALUE_ID

MODEL_ID

NUMBER

トリプルが属するRDFモデルに対応するID。

COST

NUMBER

(今後使用予定)

CTXT1

NUMBER

(予約済の列。ファイングレイン・アクセス制御に使用可能)

CTXT2

VARCHAR2(4000)

(今後使用予定)

DISTANCE

NUMBER

(今後使用予定)

EXPLAIN

VARCHAR2(4000)

(今後使用予定)

PATH

VARCHAR2(4000)

(今後使用予定)

G_ID

NUMBER

トリプルのグラフ名のテキスト値に対応するVALUE_ID。Nullはデフォルト・グラフを示します(「名前付きグラフ」を参照)。

LINK_ID

VARCHAR2(71)

一意のトリプル識別子の値。(現在は計算結果列ですが、将来のリリースでは定義が変更される可能性があります。)

注意:

表1-2の列P_VALUE_ID、START_NODE_ID、END_NODE_ID、CANON_END_NODE_IDおよびG_IDでは、実際のID値は対応する字句の値から計算されます。ただし、ある字句の値が常に同じID値にマップされるとはかぎりません。

1.3.2

MDSYS.RDF_VALUE$表には、RDF文を表すために使用される主語、プロパティおよび目的語に関する情報が含まれます。この表には、これらの情報の3要素に対応するテキスト値(URIまたはリテラル)が、各トリプルの要素ごとに用意された個別の行を使用して一意に格納されます。

Oracleでは、MDSYS.RDF_VALUE$表が自動的に管理されます。ユーザーがこのビューを直接変更することはできません。たとえば、このビューでSQLのINSERT、UPDATEまたはDELETE文を使用することはできません。

表1-3に、RDF_VALUE$表の列を示します。

表1-3 MDSYS.RDF_VALUE$表の列

列名 データ型 説明

VALUE_ID

NUMBER

一意の値ID番号(自動生成)。

VALUE_TYPE

VARCHAR2(10)

VALUE_NAME列に格納されたテキスト情報のタイプ。使用される値は、UR(URI)、BN(空白ノード)、PL(プレーン・リテラル)、PL@(言語タグ付きのプレーン・リテラル)、PLL(プレーン・ロング・リテラル)、PLL@(言語タグ付きのプレーン・ロング・リテラル)、TL(型付きリテラル)またはTLL(型付きロング・リテラル)です。ロング・リテラルは、4000バイトを超えるリテラルです。

VNAME_PREFIX

VARCHAR2(4000)

字句の値の長さが4000バイト以下の場合、この列に字句の値の一部である接頭辞が格納されます。接頭辞の計算には、SEM_APIS.VALUE_NAME_PREFIXファンクションを使用できます。たとえば、山カッコを除く字句<http://www.w3.org/1999/02/22-rdf-syntax-ns#type>の一部に対応する接頭辞は、http://www.w3.org/1999/02/22-rdf-syntax-ns#です。

VNAME_SUFFIX

VARCHAR2(512)

字句の値の長さが4000バイト以下の場合、この列に字句の値の一部である接尾辞が格納されます。接尾辞の計算には、SEM_APIS.VALUE_NAME_SUFFIXファンクションを使用できます。VNAME_PREFIX列の説明に記載されている字句の値の場合、接尾辞はtypeです。

LITERAL_TYPE

VARCHAR2(4000)

型付きリテラルの場合は型情報、それ以外の場合はNULL。たとえば、1999-08-16という作成日を示す行の場合、VALUE_TYPE列にはTLが格納され、LITERAL_TYPE列にはhttp://www.w3.org/2001/XMLSchema#dateが格納されます。

LANGUAGE_TYPE

VARCHAR2(80)

言語タグ付きのリテラル(つまり、VALUE_TYPEがPL@またはPLL@の場合)の言語タグ(フランス語の場合のfrなど)。それ以外の場合、この列はNULL値です。

CANON_ID

NUMBER

現在の字句の値に対応する正規形の字句の値のID。(この列の使用は将来のリリースで変更される可能性があります。)

COLLISION_EXT

VARCHAR2(64)

字句の値の衝突処理に使用されます。(この列の使用は将来のリリースで変更される可能性があります。)

CANON_COLLISION_EXT

VARCHAR2(64)

正規形の字句の値の衝突処理に使用されます。(この列の使用は将来のリリースで変更される可能性があります。)

ORDER_TYPE

NUMBER

データ型に基づくオーダーを表します。ORDER BY問合せのパフォーマンスを向上させるために使用します。

ORDER_NUM

NUMBER

数の型に対するオーダーを表します。ORDER BY問合せのパフォーマンスを向上させるために使用します。

ORDER_DATE

TIMESTAMPWITHTIMEZONE

日付の型に基づいたオーダーを表します。ORDER BY問合せのパフォーマンスを向上させるために使用します。

LONG_VALUE

CLOB

字句の値の長さが4000バイトを超える場合の文字列。それ以外の場合、この列はNULL値です。

GEOM

SDO_GEOMETRY

空間索引が定義されている場合はジオメトリ値。

VALUE_NAME

VARCHAR2(4000)

これは計算結果列です。字句の値の長さが4000バイト以下の場合、この列の値はVNAME_PREFIX列とVNAME_SUFFIX列の値を連結したものになります。

1.3.2.1 トリプルの一意性とリテラルのデータ型

重複するトリプルはデータベースに格納されません。あるトリプルが既存のトリプルと重複していないかどうかをチェックするため、新規トリプルの主語、プロパティおよび目的語は、指定したモデルのトリプル値と照合されます。新規の主語、プロパティおよび目的語がすべてURIの場合、それらの値が完全に一致した場合に重複であると判定されます。ただし、新規トリプルの目的語がリテラルの場合、主語とプロパティが完全に一致し、目的語の値が(正規化したときに)一致した場合に重複であると判定されます。たとえば、次の2つのトリプルは重複しています。

<eg:a> <eg:b> <"123"^^http://www.w3.org/2001/XMLSchema#int>
<eg:a> <eg:b> <"123"^^http://www.w3.org/2001/XMLSchema#unsignedByte>

2番目のトリプルは、1番目のトリプルの重複と判定されます。"123"^^<http://www.w3.org/2001/XMLSchema#int>には、(正規化したときに"123"^^<http://www.w3.org/2001/XMLSchema#unsignedByte>と等価の値が含まれるためです。2つのエンティティを同じ値に簡略化できる場合、それらのエンティティは正規化後に等価となります。

RDF以外の例をあげると、A*(B-C)A*B-C*A(B-C)*Aおよび-A*C+A*Bは、すべて同じ正規形に変換されます。

注意:

重複したトリプルとクワッドはMDSYS.RDFM_<model>ビューの基礎となる表パーティションには格納されませんが、重複した行がアプリケーション表に含まれることはあります。たとえば、トリプルがアプリケーション表に複数回挿入された場合、MDSYS.RDFM_<model>ビューには1つしか表示されませんが、アプリケーション表内では複数行を占めます。

字句形式の値ベースの一致は、次のデータ型でサポートされます。

  • STRING: プレーン・リテラル、xsd:stringとその一部のXMLスキーマ・サブタイプ

  • NUMERIC: xsd:decimalとそのXMLスキーマ・サブタイプ、xsd:floatおよびxsd:double。(float/double INF、-INFおよびNaN値はサポートされません。)

  • DATETIME: タイムゾーンのサポート付きのxsd:datetime。(タイムゾーンなしの場合も、単一値に対して"2004-02-18T15:12:54""2004-02-18T15:12:54.0000"などの複数の表現が存在します。)

  • DATE: タイムゾーン付きまたはタイムゾーンなしのxsd:date

  • OTHER: その他すべて。(異なる表現を一致する試みは行われません。)

xsd:time型とxsd:dateTime型のリテラルにタイムゾーンが存在する場合、正規化が実行されます。

次の名前空間定義にはxmlns:xsd="http://www.w3.org/2001/XMLSchema"が使用されます。

RDF_VALUE$表で最初に出現するリテラルは、正規形として扱われ、それぞれCPLCPL@CTLCPLLCPLL@またはCTLLというVALUE_TYPE値が適切に割り当てられます(つまり、正規形の場合は実際の値タイプにCという接頭辞が付けられます)。以前挿入されたリテラルと同じ正規形を持つ(ただし異なる字句表現の)リテラルがRDF_VALUE$表に挿入されると、その新しい挿入に対してそれぞれPLPL@TLPLLPLL@またはTLLというVALUE_TYPE値が適切に割り当てられます。

したがって、正規化後に等価となる異なる字句表現を持つテキスト値は、RDF_VALUE$表に格納されますが、正規化後に等価となるトリプルはデータベースに格納されません。

1.3.3 主語と目的語

RDFの主語と目的語は、セマンティク・データ・ネットワークのノードにマップされます。主語のノードはリンクの開始ノードで、目的語のノードはリンクの終了ノードです。リテラル以外のノード(URIや空白ノード)は、主語および目的語のノードとして使用できます。リテラルは、目的語のノードとしてのみ使用できます。

1.3.4 空白ノード

空白ノードは、セマンティク・ネットワークの主語および目的語のノードとして使用できます。空白ノード識別子は、1つのセマンティク・モデル内を有効範囲とする点において、URIとは異なります。つまり、単一のセマンティク・モデル内に同じ空白ノード識別子が複数出現した場合、それらは常に同じリソースを示しますが、異なる2つのセマンティク・モデル内に同じ空白ノード識別子が出現した場合、それらは同じリソースを示しません。

Oracleセマンティク・ネットワークにおいて、この動作は、空白ノードは常に1つのセマンティク・モデル内で再利用され、2つの異なるモデル間では再利用されない(つまり、同じ空白ノード識別子が使用される場合は同じリソースを表している)という要件の適用によりモデル化されます。このため、空白ノードを含むトリプルをモデルに挿入する場合、空白ノードの再利用をサポートするSDO_RDF_TRIPLE_Sコンストラクタを使用する必要があります。

1.3.5 プロパティ

プロパティは、開始ノード(主語)と終了ノード(目的語)を備えたリンクにマップされます。したがって、1つのリンクは完全なトリプルを表します。

トリプルがモデルに挿入されると、主語、プロパティおよび目的語のテキスト値について、それらがすでにデータベースに存在するかどうかがチェックされます。他のモデルの以前の文に基づくテキスト値がすでに存在する場合、新規エントリは作成されません。テキスト値が存在しない場合、RDF_VALUE$表(「文」を参照)に新規行が挿入されます。

1.3.6 推論: ルールとルールベース

推論は、ルールに基づいて論理的な推測を行う機能です。推論により、文字列などの値に基づく構文的な一致機能ではなく、データの各要素間の意味的な関係に基づいてセマンティクな一致機能を実行する問合せを作成できます。推論では、ルールベースに格納されたルールを使用し、ルールには、Oracleに付属するものとユーザーが定義するものがあります。

図1-2に、モデル・データと1つ以上のルールベースにおけるルールの適用から推論されたトリプル・セットを示します。この図の場合、データベースには任意の数のセマンティク・モデル、ルールベース、および推論されたトリプル・セットがあり、推論されたトリプル・セットは1つ以上のルールベースのルールを使用して導出されます。

ルールは、セマンティク・データから推論を導く際に適用できるオブジェクトです。ルールは、名前で識別され、次の要素で構成されます。

  • 前件に対応するIF側パターン

  • IF側パターンで一致したサブグラフをさらに絞り込むオプションのフィルタ条件

  • 後件に対応するTHEN側パターン

たとえば、「会議の議長は会議のレビューアでもある」というルールは、次のように表現されます。

('chairpersonRule', -- rule name
 '(?r :ChairPersonOf ?c)', -- IF side pattern
 NULL,  -- filter condition
 '(?r :ReviewerOf ?c)', -- THEN side pattern
 SEM_ALIASES (SEM_ALIAS('', 'http://some.org/test/'))
)

この場合、ルールにフィルタ条件はないため、表現内のその構成要素はNULLです。パフォーマンスを最大化するには、ルールのTHEN側に単一のトリプル・パターンを使用します。ルールのTHEN側に複数のトリプル・パターンが含まれる場合、THEN側でそれぞれ単一のトリプル・パターンを含むようにそれを複数のルールに簡単に分割できます。

ルールベースは、ルールを含むオブジェクトです。Oracleには、次のルールベースが付属しています。

  • RDFS

  • RDF (RDFSのサブセット)

  • OWLSIF (空)

  • RDFS++ (空)

  • OWL2RL (空)

  • OWLPrime (空)

  • SKOSCORE (空)

RDFSおよびRDFルールベースは、SEM_APIS.CREATE_SEM_NETWORKプロシージャをコールしてRDFサポートをデータベースに追加すると作成されます。RDFSルールベースでは、RDFS伴意ルールを実装します。詳細は、http://www.w3.org/TR/rdf-mt/にあるWorld Wide Web Consortium (W3C)のドキュメント 「RDF Semantics」を参照してください。RDFルールベースは、RDF伴意ルール(RDFS伴意ルールのサブセット)を表します。これらのルールベースの内容は、MDSYS.SEMR_RDFSおよびMDSYS.SEMR_RDFビューで確認できます。

SEM_APIS.CREATE_RULEBASEプロシージャを使用してユーザー定義のルールベースを作成することも可能です。ユーザー定義のルールベースを使用すると、特殊化された推論機能を追加できます。

ルールベースごとに、ルールベースのルールを保持するためのシステム表と、MDSYS.SEMR_rulebase-nameという形式の名前を持つシステム・ビューが作成されます(たとえば、FAMILY_RBというルールベースの場合、 MDSYS.SEMR_FAMILY_RBという名前になります)。ルールベースのルールを挿入、削除および変更するには、このビューを使用する必要があります。表1-4に、各MDSYS.SEMR_rulebase-nameビューの列を示します。

表1-4 MDSYS.SEMR_rulebase-nameビューの列

列名 データ型 説明

RULE_NAME

VARCHAR2(30)

ルールの名前

ANTECEDENTS

VARCHAR2(4000)

前件に対応するIF側パターン

FILTER

VARCHAR2(4000)

IF側パターンで一致したサブグラフをさらに絞り込むフィルタ条件。NULLは、適用されるフィルタ条件がないことを示します。

CONSEQUENTS

VARCHAR2(4000)

後件に対応するTHEN側パターン

ALIASES

SEM_ALIASES

使用される1つ以上の名前空間。(SEM_ALIASESデータ・タイプの説明は、「SEM_MATCHテーブル・ファンクションを使用したセマンティク・データの問合せ」を参照してください。)

すべてのルールベースに関する情報は、MDSYS.SEM_RULEBASE_INFOビューに保持されます。表1-5に、このビューの列を示します(1つの行が1つのルールベースに対応します)。

表1-5 MDSYS.SEM_RULEBASE_INFOビューの列

列名 データ型 説明

OWNER

VARCHAR2(30)

ルールベースの所有者

RULEBASE_NAME

VARCHAR2(25)

ルールベースの名前

RULEBASE_VIEW_NAME

VARCHAR2(30)

ルールベースのルールを挿入、削除または変更する任意のSQL文で使用する必要のあるビューの名前

STATUS

VARCHAR2(30)

VALID(ルールベースが有効の場合)、INPROGRESS(ルールベースが作成中の場合)またはFAILED(ルールベースの作成中にシステム障害が発生した場合)が含まれます。

例1-1 ルールベースへのルールの挿入

例1-1では、family_rbというルールベースを作成し、そのfamily_rbルールベースにgrandparent_ruleというルールを挿入します。このルールは、ある人物がある子の親であり、その子がさらに別の子の親である場合、その人物が自分の子供の子供に対する祖父母である(つまり、自分の子供の子供に関してgrandParentOf関係を持つ)ことを示します。また、使用する名前空間も指定します。((この例は、 「例: 家系の情報」例1-110の抜粋です。)

EXECUTE SEM_APIS.CREATE_RULEBASE('family_rb');

INSERT INTO mdsys.semr_family_rb VALUES(
  'grandparent_rule',
  '(?x :parentOf ?y) (?y :parentOf ?z)',
  NULL,
  '(?x :grandParentOf ?z)', 
  SEM_ALIASES(SEM_ALIAS('','http://www.example.org/family/')));

例1-1に示されている祖父母ルールの種類は、OWL 2プロパティ・チェーン構成要素を使用して実装できることに注意してください。プロパティ・チェーンの処理の詳細は、「プロパティ・チェーンの処理」を参照してください。

例1-2 推論でのルールベースの使用

SEM_MATCH表関数(「SEM_MATCH表関数を使用したセマンティク・データの問合せ」を参照)を呼び出す場合に1つ以上のルールベースを指定することで、セマンティク・データに対する問合せの動作を制御できます。例1-2では、family_rbルールベースと、例1-1で作成したgrandParentOf関係を参照して、すべての祖父(祖父母の男性の方)とその孫を検索します。((この例は、 「例: 家系の情報」例1-110の抜粋です。)

-- Select all grandfathers and their grandchildren from the family model.
-- Use inferencing from both the RDFS and family_rb rulebases.
SELECT x grandfather, y grandchild
  FROM TABLE(SEM_MATCH(
    '{?x :grandParentOf ?y . ?x rdf:type :Male}',
    SEM_Models('family'),
    SEM_Rulebases('RDFS','family_rb'), 
    SEM_ALIASES(SEM_ALIAS('','http://www.example.org/family/')),
    null));

ネイティブOWL推論のサポートの詳細は、「OWL推論の使用方法」を参照してください。

1.3.7 伴意(ルール索引)

伴意(ルール索引)は、指定したルールベースのセットを指定したモデルのセットに適用することで推論できる計算済のトリプルを含むオブジェクトです。SEM_MATCH問合せで任意のルールベースを参照する場合、問合せ内のルールベースとモデルの組合せごとに伴意が存在している必要があります。

伴意を作成するには、SEM_APIS.CREATE_ENTAILMENTプロシージャを使用します。伴意を削除するには、SEM_APIS.DROP_ENTAILMENTプロシージャを使用します。

伴意を作成すると、その伴意に関連付けられたトリプルのビューもMDSYSスキーマに作成されます。このビューは、SEMI_entailment-nameという形式の名前を持ち、伴意の所有者および適切な権限を持つユーザーにのみ表示されます。各MDSYS.SEMI_entailment-nameビューには、ネットワークにリンクとして格納されたトリプルごとに1つの行が保持され、また、SEMM_model-nameビューと同じ列が含まれます(「モデルのメタデータ」表1-2を参照)。

すべての伴意に関する情報は、MDSYS.SEM_RULES_INDEX_INFOビューに保持されます。表1-6に、このビューの列を示します(1つの行が1つの伴意に対応します)。

表1-6 MDSYS.SEM_RULES_INDEX_INFOビューの列

列名 データ型 説明:

OWNER

VARCHAR2(30)

伴意の所有者

INDEX_NAME

VARCHAR2(25)

伴意の名前

INDEX_VIEW_NAME

VARCHAR2(30)

伴意のルールを挿入、削除または変更する任意のSQL文で使用する必要のあるビューの名前

STATUS

VARCHAR2(30)

VALID (伴意が有効の場合)、INVALID (伴意が無効の場合)、INCOMPLETE (伴意が不完全の場合(INVALIDと似ていますが、再作成にそれほど時間がかかりません))、INPROGRESS (伴意が作成中の場合)またはFAILED (伴意の作成中にシステム障害が発生した場合)が含まれます。

MODEL_COUNT

NUMBER

伴意に含まれるモデルの数

RULEBASE_COUNT

NUMBER

伴意に含まれるルールベースの数

モデルやルールベースなど、伴意に関連するすべてのデータベース・オブジェクトの情報は、MDSYS.SEM_RULES_INDEX_DATASETSビューに保持されます。表1-7に、このビューの列を示します(1つの行がすべての列の値の一意の組合せに対応します)。

表1-7 MDSYS.SEM_RULES_INDEX_DATASETSビューの列

列名 データ型 説明

INDEX_NAME

VARCHAR2(25)

伴意の名前

DATA_TYPE

VARCHAR2(8)

伴意に含まれるデータのタイプ。たとえば、MODELおよびRULEBASEです。

DATA_NAME

VARCHAR2(25)

DATA_TYPE列に含まれるタイプのオブジェクトの名前

例1-3では、familyモデルとRDFSおよびfamily_rbルールベースを使用して、family_rb_rix_familyという伴意を作成します。((この例は、 「例: 家系の情報」例1-110の抜粋です。)

例1-3 伴意の作成

BEGIN
  SEM_APIS.CREATE_ENTAILMENT(
    'rdfs_rix_family',
    SEM_Models('family'),
    SEM_Rulebases('RDFS','family_rb'));
END;
/

1.3.8 仮想モデル

仮想モデルとは、SEM_MATCH問合せで使用できる論理グラフのことです。仮想モデルは、1つ以上のモデルまたは伴意、あるいはその両方に対してUNIONまたはUNION ALL操作を実行した結果です。

仮想モデルを使用する場合の利点は次のとおりです。

  • セマンティク・データのアクセス権限の管理を簡略化できます。たとえば、3つのモデルおよびOWLPrimeルールベースに基づいて、3つのセマンティク・モデルおよび1つの伴意を作成したとします。仮想モデルを使用しない場合は、各モデルおよび伴意に対してアクセス権限の付与および取消しを個別に行う必要があります。しかし、3つのモデルと伴意を含む仮想モデルを作成すると、この1つの仮想モデルに対してのみアクセス権限の付与および取消しを行うだけで済みます。

  • セマンティク・モデルのすばやい更新を容易にできます。たとえば、仮想モデルVM1にモデルM1と伴意R1が含まれるとし(VM1 = M1 UNION ALL R1)、また、セマンティク・モデルM1_UPDは追加のトリプルで更新されたM1のコピーであり、R1_UPDはM1_UPDに作成された伴意であるとします。この場合、VM1に対するユーザー問合せで更新済のモデルおよび伴意が使用されるように、仮想モデルVM1を再定義できます(VM1 = M1_UPD UNION ALL R1_UPD)。

  • 仮想モデルへの問合せは、SEM_MATCH問合せでの複数のモデルの問合せと同等であるため、問合せの指定を簡略化できます。たとえば、モデルm1、m2およびm3がすでに存在し、OWLPrimeルールベースを使用してm1、m2およびm3に対して伴意が作成されているとします。仮想モデルvm1を次のように作成できます。

    EXECUTE sem_apis.create_virtual_model('vm1', sem_models('m1', 'm2', 'm3'), 
                                          sem_rulebases('OWLPRIME'));
    

    仮想モデルを問い合せるには、SEM_MATCH問合せのモデルと同様の仮想モデル名を使用します。たとえば、仮想モデルに対する次の問合せがあるとします。

    SELECT * FROM TABLE (sem_match('{…}', sem_models('vm1'), null, …));
    

    これは、すべての個別モデルに対する次の問合せと同等です。

    SELECT * FROM TABLE (sem_match('{…}', sem_models('m1', 'm2', 'm3'), 
                                          sem_rulebases('OWLPRIME'), …));
    

    仮想モデルに対するSEM_MATCH問合せでは、それぞれのモデルおよび伴意のUNIONまたはUNION ALLを問い合せることなく、SEMVまたはSEMUビューを問い合せます(デフォルトはSEMUで、'ALLOW_DUP=T'オプションが指定されている場合はSEMV)。これらのビューおよびオプションの詳細は、SEM_APIS.CREATE_VIRTUAL_MODELプロシージャのリファレンスの項を参照してください。

仮想モデルは、ビューを使用し(この項の後の部分を参照)、いくつかのメタデータ・エントリを追加しますが、システム記憶域要件はそれほど増大しません。

仮想モデルを作成するには、SEM_APIS.CREATE_VIRTUAL_MODELプロシージャを使用します。仮想モデルを削除するには、SEM_APIS.DROP_VIRTUAL_MODELプロシージャを使用します。仮想モデルのコンポーネント・モデル、ルールベースまたは伴意が削除されると、その仮想モデルは自動的に削除されます。それを削除することなく仮想モデルを置き換えるには、SEM_APIS.CREATE_VIRTUAL_MODELプロシージャをREPLACE=Tオプションとともに使用します。仮想モデルを置き換えると、それを再定義する一方で、任意のアクセス権限を保持することができます。

仮想モデルを問い合せるには、例1-4に示すとおり、SEM_MATCH表関数のmodelsパラメータで仮想モデル名を指定します。

SEM_MATCHテーブル・ファンクションの詳細は、「SEM_MATCHテーブル・ファンクションを使用したセマンティク・データの問合せ」を参照してください。この項には、仮想モデルを問い合せるときの特定の属性の使用方法が示されています。

仮想モデルを作成すると、MDSYS.SEM_MODEL$ビューに仮想モデルのエントリが作成されます(「モデルのメタデータ」表1-1を参照)。ただし、表1-8の説明にあるとおり、いくつかの列では、仮想モデルの値はセマンティク・モデルの値と異なります。

表1-8 仮想モデルのMDSYS.SEM_MODEL$ビューの列の説明

列名 データ型 説明

OWNER

VARCHAR2(30)

仮想モデルの所有者のスキーマ。

MODEL_ID

NUMBER

一意のモデルID番号(自動生成)。これが仮想モデルであることを表すため、負の数になります。

MODEL_NAME

VARCHAR2(25)

仮想モデルの名前。

TABLE_NAME

VARCHAR2(30)

仮想モデルの場合はNULL。

COLUMN_NAME

VARCHAR2(30)

仮想モデルの場合はNULL。

MODEL_TABLESPACE_NAME

VARCHAR2(30)

仮想モデルの場合はNULL。

すべての仮想モデルに関する情報は、MDSYS.SEM_VMODEL_INFOビューに保持されます。表1-9に、このビューの列を示します(1つの行が1つの仮想モデルに対応します)。

表1-9 MDSYS.SEM_VMODEL_INFOビューの列

列名 データ型 説明

OWNER

VARCHAR2(30)

仮想モデルの所有者。

VIRTUAL_MODEL_NAME

VARCHAR2(25)

仮想モデルの名前。

UNIQUE_VIEW_NAME

VARCHAR2(30)

仮想モデル内に一意のトリプルを含むビューの名前。ビューが作成されていない場合は、NULL。

DUPLICATE_VIEW_NAME

VARCHAR2(30)

仮想モデル内に重複するトリプル(ある場合)を含むビューの名前。

STATUS

VARCHAR2(30)

VALID(関連付けられた伴意が有効の場合)、INVALID(伴意が無効の場合)、INCOMPLETE(伴意が不完全の場合(INVALIDと似ていますが、再作成にそれほど時間がかかりません))、INPROGRESS(伴意が作成中の場合)、FAILED(伴意の作成中にシステム障害が発生した場合)、NORIDX(伴意が仮想モデルと関連付けられている場合)が含まれます。

複数の伴意がある場合は、すべてのコンポーネント伴意のうち最も低いステータスが、仮想モデルのステータスとして使用されます(INVALID < INCOMPLETE < VALID)。

MODEL_COUNT

NUMBER

仮想モデル内のモデルの数。

RULEBASE_COUNT

NUMBER

仮想モデルに使用されるルールベースの数。

RULES_INDEX_COUNT

NUMBER

仮想モデル内の伴意の数。

すべてのオブジェクト(モデル、ルールベースおよび伴意)に関する情報は、MDSYS.SEM_VMODEL_DATASETSビューに保持されます。表1-10に、このビューの列を示します(1つの行がすべての列の値の一意の組合せに対応します)。

表1-10 MDSYS.SEM_VMODEL_DATASETSビューの列

列名 データ型 説明

VIRTUAL_MODEL_NAME

VARCHAR2(25)

仮想モデルの名前。

DATA_TYPE

VARCHAR2(8)

仮想モデルに含まれるオブジェクトのタイプ。例: MODEL(セマンティク・モデル)、RULEBASE(ルールベース)、RULEIDX(伴意)。

DATA_NAME

VARCHAR2(25)

DATA_TYPE列に含まれるタイプのオブジェクトの名前

例1-4 仮想モデルの問合せ

SELECT COUNT(protein)
  FROM TABLE (SEM_MATCH (
    '{?protein rdf:type :Protein .
      ?protein :citation ?citation . 
      ?citation :author "Bairoch A."}',
    SEM_MODELS('UNIPROT_VM'), 
    NULL, 
    SEM_ALIASES(SEM_ALIAS('', 'http://purl.uniprot.org/core/')),
    NULL, 
    NULL, 
    'ALLOW_DUP=T'));

1.3.9 名前付きグラフ

RDFセマンティク・グラフは名前付きグラフの使用をサポートしており、これについてはW3C勧告の「SPARQL Query Language for RDF」のRDFデータセットに関する項(http://www.w3.org/TR/rdf-sparql-query/#rdfDataset)で説明されています。

このサポートは、従来の主語、述語、目的語で構成されるRDFトリプルを、グラフ名を表す追加の構成要素を含めるように拡張することで実現されます。拡張されたRDFトリプルは、4つの構成要素を含みますが、このドキュメントでは引き続きRDFトリプルと呼びます。また、次の用語が使用されることもあります。

  • N-Triple: 拡張トリプルを許可しない形式です。したがって、n-tripleは3つのコンポーネントを持つトリプルのみを含むことができます。

  • N-Quad: 通常のトリプル(3つのコンポーネント)と拡張トリプル(グラフ名を含む4つのコンポーネント)を許可する形式です。詳細は、http://www.w3.org/TR/2013/NOTE-n-quads-20130409/を参照してください。

    拡張トリプルを含むファイル(通常は標準トリプルが混在)をOracle Databaseにロードする場合、入力ファイルはN-Quad形式である必要があります。

RDFトリプルのグラフ名の構成要素は、NULLまたはURIである必要があります。これがNULLの場合、RDFトリプルはデフォルト・グラフに属していると言われます(それ以外の場合、URIで指定された名前を持つ名前付きグラフに属していると言われます)。

また、SDO_RDF_TRIPLE_Sオブジェクト型(「セマンティク・データの型、コンストラクタ、およびメソッド」を参照)の名前付きグラフをサポートするため、モデル-グラフ(モデルとグラフ(存在する場合)の組合せ)を指定するための新しい構文が用意され、RDF_M_ID属性はモデル-グラフの識別子(グラフ(存在する場合)のモデルIDと値IDの組合せ)を保持します。モデル-グラフの名前をmodel_nameとして指定し、グラフが存在する場合は、その後にコロン(:)区切り文字とグラフ名が続きます(これはURIであり、山カッコ< >で囲まれる必要があります)。

たとえば、医療データセットでは、各RDFトリプルの名前付きグラフの構成要素は患者の識別子に基づくURIになるため、一意の患者と同じ数の名前付きグラフが存在することになります(それぞれの名前付きグラフは特定の患者のデータで構成されます)。

名前付きグラフに特定の操作を実行する方法の詳細は、次の項を参照してください。

1.3.9.1 名前付きグラフ・サポートに関連したデータ形式

TriGおよびN-QUADSの2つは、グラフ名(またはコンテキスト)をトリプル・データに与えるための一般的なデータ形式です。(2011年11月の時点では、どちらも標準形式ではありませんでした。)グラフ名(コンテキスト)は様々な方法で使用できます。典型的な使用方法には、管理、ローカライズされた問合せ、ローカライズされた推論および来歴を容易にするためのトリプルのグループ化がありますが、これに限定されるものではありません。

例1-5 TriG形式でエンコードされたRDFデータ

例1-5は、TriG形式でエンコードされるRDFデータセットを示しています。デフォルト・グラフと名前付きグラフが含まれます。

@prefix foaf: <http://xmlns.com/foaf/0.1/> .
@prefix dc: <http://purl.org/dc/elements/1.1/> .
 
# Default graph
{
  <http://my.com/John> dc:publisher <http://publisher/Xyz> .
}
 
# A named graph
<http://my.com/John> {
  <http://my.com/John> foaf:name "John Doe" .
}

例1-5のTriGファイルをDatasetGraphOracleSemオブジェクトにロード(たとえば、「RDF Semantic Graph Support for Apache Jenaを使用したバルク・ロード」例6-12を使用)する場合に、定数"N-QUADS""TRIG"に置き換えると、デフォルト・グラフ内のトリプルは、トリプルとしてnullグラフ名とともにOracle Databaseにロードされ、名前付きグラフ内のトリプルは指定されたグラフ名とともにOracle Databaseにロードされます。

例1-6 N-QUADS形式の表現

N-QUADS形式は、オプションの4番目の列(グラフ名またはコンテキスト)を追加することで既存のN-TRIPLES形式を単純に拡張したものです。例1-6に、例1-5に基づくTriGファイルのN-QUADS形式の表現を示します。

<http://my.com/John> <http://purl.org/dc/elements/1.1/publisher> <http://publisher/Xyz> .
<http://my.com/John> <http://xmlns.com/foaf/0.1/name> "John Doe" <http://my.com/John>

N-QUADSファイルをDatasetGraphOracleSemオブジェクトにロードすると(例6-12を参照)、4つ目の列のない行はnullグラフ名を持つトリプルとしてOracle Databaseにロードされ、4つ目の列がある行は指定されたグラフ名でOracle Databaseにロードされます。

1.3.10 セマンティク・データのセキュリティ上の考慮事項

セマンティク・データを使用する場合、次のデータベース・セキュリティの考慮事項が適用されます。

  • モデルまたは伴意を作成すると、関連ビューに対するGRANTオプション付きのSELECT権限が所有者に付与されます。これらのビューに対してSELECT権限を持つユーザーは、関連モデルまたは伴意に対してSEM_MATCH問合せを実行できます。

  • ルールベースを作成すると、ルールベースに対するGRANTオプション付きのSELECT、INSERT、UPDATEおよびDELETE権限が所有者に付与されます。ルールベースに対してSELECT権限を持つユーザーは、ルールベースを含む伴意を作成できます。INSERT、UPDATEおよびDELETE権限により、ルールベースを変更できるユーザーと、その変更方法が制御されます。

  • モデルに対してデータ操作言語(DML)の操作を実行する場合、ユーザーは対応する実表に対するDML権限を持っている必要があります。

  • モデルに対応する実表の作成者は、他のユーザーに権限を付与できます。

  • ルールベースに対してデータ操作言語(DML)の操作を実行する場合、ユーザーは対応するデータベース・ビューに対する適切な権限を持っている必要があります。

  • モデルの作成者は、対応するデータベース・ビューに対するSELECT権限を他のユーザーに付与できます。

  • ユーザーは、対応するデータベース・ビューに対するSELECT権限を持っているモデルのみを問い合せることができます。

  • モデルまたはルールベースを削除できるのは、その作成者のみです。

1.4 セマンティク・メタデータ表およびビュー

Oracle Databaseでは、セマンティク・データに関連するメタデータを保持するために、MDSYSスキーマで複数の表およびビューが管理されます。

これらの表およびビューの一部は、「セマンティク・データを使用するためのクイック・スタート」に記載されているSEM_APIS.CREATE_SEM_NETWORKプロシージャによって作成され、一部は必要な場合にのみ作成されます。表1-11に、そうした表とビューの一覧をアルファベット順に示します。(また、Oracleで内部的に使用するためにいくつかの表およびビューも作成されますが、それらの表およびビューにはDBA権限を持つユーザーのみがアクセスできます。)

表1-11 セマンティク・メタデータ表およびビュー

名前 含まれる情報 参照先

RDF_CRS_URI$

利用可能なEPSG空間参照システムURI

空間のサポート

RDF_VALUE$

文を表すのに使用される主語、プロパティおよび目的語

RDFOLS_SECURE_RESOURCE

Oracle Label Security (OLS)ポリシーで保護されたリソースと、それらのリソースに関連付けられた機密性ラベル

RDFOLS_SECURE_RESOURCEビュー

SEM_DTYPE_INDEX_INFO

ネットワークのすべてのデータ型索引

データ型索引の使用

SEM_MODEL$

データベースに定義されているすべてのモデル

モデルのメタデータ

SEM_NETWORK_INDEX_INFO$

セマンティク・ネットワーク索引

MDSYS.SEM_NETWORK_INDEX_INFOビュー

SEM_RULEBASE_INFO

ルールベース

推論: ルールとルールベース

SEM_RULES_INDEX_DATASETS

伴意で使用されるデータベース・オブジェクト

伴意(ルール索引)

SEM_RULES_INDEX_INFO

伴意(ルール索引)

伴意(ルール索引)

SEM_VMODEL_INFO

仮想モデル

仮想モデル

SEM_VMODEL_DATASETS

仮想モデルで使用されるデータベース・オブジェクト

仮想モデル

SEMCL_entailment-name

owl:sameAsクリーク・メンバーと正規形の代表

owl:sameAs推論の最適化

SEMI_entailment-name

指定した伴意のトリプル

伴意(ルール索引)

SEMM_model-name

指定したモデルのトリプル

モデルのメタデータ

SEMR_rulebase-name

指定したルールベースのルール

推論: ルールとルールベース

SEMU_virtual-model-name

仮想モデル内の一意のトリプル

仮想モデル

SEMV_virtual-model-name

仮想モデル内のトリプル

仮想モデル

1.5 セマンティク・データの型、コンストラクタおよびメソッド

SDO_RDF_TRIPLEオブジェクト型は、トリプル形式のセマンティク・データを表し、SDO_RDF_TRIPLE_Sオブジェクト型(_Sは格納の意味)は、データベースに永続セマンティク・データを格納します。

実際のセマンティク・データはRDFスキーマにのみ一元的に格納されるため、SDO_RDF_TRIPLE_S型はデータに対する参照を保持します。この型には、トリプルの一部または全部を取得するためのメソッドがあります。

注意:

空白ノードは、常に1つのRDFモデル内で再利用されます。複数のモデル間で再利用することはできません。

SDO_RDF_TRIPLE型はトリプルの表示に使用し、SDO_RDF_TRIPLE_S型はデータベース表へのトリプルの格納に使用します。

SDO_RDF_TRIPLEオブジェクト型には、次の属性が含まれます。

SDO_RDF_TRIPLE (
  subject VARCHAR2(4000), 
  property VARCHAR2(4000), 
  object VARCHAR2(10000))

SDO_RDF_TRIPLE_Sオブジェクト型には、次の属性が含まれます。

SDO_RDF_TRIPLE_S (
  RDF_C_ID NUMBER, -- Canonical object value ID
  RDF_M_ID NUMBER, -- Model (or Model-Graph) ID 
  RDF_S_ID NUMBER, -- Subject value ID
  RDF_P_ID NUMBER, -- Property value ID
  RDF_O_ID NUMBER) -- Object value ID

SDO_RDF_TRIPLE_S型には、RDFモデル(モデル-グラフ)の名前、トリプル、またはトリプルの一部(主語、プロパティまたは目的語)を取得する次のメソッドが含まれます。

GET_MODEL() RETURNS VARCHAR2
GET_TRIPLE() RETURNS SDO_RDF_TRIPLE
GET_SUBJECT() RETURNS VARCHAR2
GET_PROPERTY() RETURNS VARCHAR2
GET_OBJECT() RETURNS CLOB

例1-7に、SDO_RDF_TRIPLE_Sのメソッドをいくつか示します。

例1-7 SDO_RDF_TRIPLE_Sのメソッド

-- Find all articles that reference Article2.
SELECT a.triple.GET_SUBJECT() AS subject
    FROM articles_rdf_data a
    WHERE a.triple.GET_PROPERTY() = '<http://purl.org/dc/terms/references>' AND
    TO_CHAR(a.triple.GET_OBJECT()) = '<http://nature.example.com/Article2>';

SUBJECT                                                                         
--------------------------------------------------------------------------------
<http://nature.example.com/Article1>                                            

-- Find all triples with Article1 as subject.
SELECT a.triple.GET_TRIPLE() AS triple
    FROM articles_rdf_data a
    WHERE a.triple.GET_SUBJECT() = '<http://nature.example.com/Article1>';

TRIPLE(SUBJECT, PROPERTY, OBJECT)                                               
--------------------------------------------------------------------------------
SDO_RDF_TRIPLE('<http://nature.example.com/Article1>', '<http://purl.org/dc/elem
ents/1.1/title>', '"All about XYZ"')                                            
                                                                                
SDO_RDF_TRIPLE('<http://nature.example.com/Article1>', '<http://purl.org/dc/elem
ents/1.1/creator>', '"Jane Smith"')                                             
                                                                                
SDO_RDF_TRIPLE('<http://nature.example.com/Article1>', '<http://purl.org/dc/term
s/references>', '<http://nature.example.com/Article2>')                         
                                                                                
SDO_RDF_TRIPLE('<http://nature.example.com/Article1>', '<http://purl.org/dc/term
s/references>', '<http://nature.example.com/Article3>')                         

TRIPLE(SUBJECT, PROPERTY, OBJECT)                                               
--------------------------------------------------------------------------------
                                                                                
-- Find all objects where the subject is Article1.
SELECT a.triple.GET_OBJECT() AS object
    FROM articles_rdf_data a
    WHERE a.triple.GET_SUBJECT() = '<http://nature.example.com/Article1>';

OBJECT                                                                          
--------------------------------------------------------------------------------
"All about XYZ"                                                                 
"Jane Smith"                                                                    
<http://nature.example.com/Article2>                                            
<http://nature.example.com/Article3>                                            

-- Find all triples where Jane Smith is the object.
SELECT a.triple.GET_TRIPLE() AS triple
    FROM articles_rdf_data a
    WHERE TO_CHAR(a.triple.GET_OBJECT()) = '"Jane Smith"';

TRIPLE(SUBJECT, PROPERTY, OBJECT)                                               
--------------------------------------------------------------------------------
SDO_RDF_TRIPLE('<http://nature.example.com/Article1>', '<http://purl.org/dc/elem
ents/1.1/creator>', '"Jane Smith"')  

1.5.1 トリプルを挿入するためのコンストラクタ

次のコンストラクタ書式は、トリプルをモデル表に挿入する場合に使用できます。2つの書式の唯一の違いは、2番目の書式における目的語のデータ型がCLOBであり、非常に長いリテラルに対応できることです。

SDO_RDF_TRIPLE_S (
  model_name VARCHAR2, -- Model name
  subject    VARCHAR2, -- Subject
  property   VARCHAR2, -- Property
  object     VARCHAR2) -- Object
  RETURN     SELF;

SDO_RDF_TRIPLE_S (
  model_name VARCHAR2, -- Model name
  subject    VARCHAR2, -- Subject
  property   VARCHAR2, -- Property
  object     CLOB) -- Object
  RETURN SELF;

GET_OBJ_VALUE() RETURN VARCHAR2;

例1-8では、1番目のコンストラクタ書式を使用して複数のトリプルを挿入します。

例1-8 トリプルを挿入するSDO_RDF_TRIPLE_Sコンストラクタ

INSERT INTO articles_rdf_data VALUES (
  SDO_RDF_TRIPLE_S ('articles','<http://nature.example.com/Article1>',
    '<http://purl.org/dc/elements/1.1/creator>',
    '"Jane Smith"'));

INSERT INTO articles_rdf_data VALUES (
  SDO_RDF_TRIPLE_S ('articles:<http://examples.com/ns#Graph1>',
    '<http://nature.example.com/Article102>',
    '<http://purl.org/dc/elements/1.1/creator>',
    '_:b1'));
 
INSERT INTO articles_rdf_data VALUES (
  SDO_RDF_TRIPLE_S ('articles:<http://examples.com/ns#Graph1>',
    '_:b2',
    '<http://purl.org/dc/elements/1.1/creator>',
    '_:b1'));

1.6 SEM_MATCH表関数を使用したセマンティク・データの問合せ

セマンティク・データを問い合せるには、SEM_MATCH表関数を使用します。

この関数には、次の属性が含まれます。

SEM_MATCH(
  query        VARCHAR2,
  models       SEM_MODELS,
  rulebases    SEM_RULEBASES,
  aliases      SEM_ALIASES,
  filter       VARCHAR2,
  index_status VARCHAR2,
  options      VARCHAR2,
  graphs       SEM_GRAPHS,
  named_graphs SEM_GRAPHS
 ) RETURN ANYDATASET;

query属性は必須です。その他の属性はオプションです(それぞれNULL値を指定できます)。

query属性は、通常は変数が含まれる1つ以上のトリプル・パターンを備えた文字列リテラル(または文字列リテラルを連結したもの)です。(query属性には、バインド変数またはバインド変数を含む式を指定することはできません。)トリプル・パターンは、ピリオドで囲まれた3つのアトムです。各アトムには、変数(?xなど)、デフォルトの名前空間およびaliases属性の値に基づいて拡張された修飾名(rdf:type)、または完全なURI (<http://www.example.org/family/Male>など)を指定できます。また、3番目のアトムには、数値リテラル(3.14など)、プレーン・リテラル("Herman"など)、言語タグ付きのプレーン・リテラル("Herman"@enなど)または型付きリテラル("123"^^xsd:intなど)を指定できます。

たとえば、次のquery属性では、3つのトリプル・パターンを使用して祖父(祖父母の男性の方)とその孫の身長を検索します。

'{ ?x :grandParentOf ?y . ?x rdf:type :Male . ?y :height ?h }'

models属性では、使用する1つ以上のモデルを指定します。そのデータ型は、TABLE OF VARCHAR2(25)という定義を持つSEM_MODELSです。仮想モデルを問い合せる場合、他のモデル名は指定せず、その仮想モデルの名前のみを指定します。(仮想モデルの詳細は、「仮想モデル」を参照してください。)

rulebases属性では、問合せに適用するルールが含まれる1つ以上のルールベースを指定します。そのデータ型は、TABLE OF VARCHAR2(25)という定義を持つSDO_RDF_RULEBASESです。仮想モデルを問い合せる場合、この属性はNULLである必要があります。

aliases属性では、デフォルトの名前空間以外に、問合せパターンの修飾名の拡張に使用する1つ以上の名前空間を指定します。そのデータ型は、TABLE OF SEM_ALIASという定義を持つSEM_ALIASESです。各SEM_ALIAS要素により、名前空間IDと名前空間値が識別されます。SEM_ALIASデータ型は、(namespace_id VARCHAR2(30), namespace_val VARCHAR2(4000))という定義を持ちます。

SEM_MATCH表関数とSEM_CONTAINSおよびSEM_RELATED演算子では、次のデフォルトの名前空間(namespace_id属性とnamespace_val属性)が使用されます。

('ogc', 'http://www.opengis.net/ont/geosparql#')
('ogcf', 'http://www.opengis.net/def/function/geosparql/')
('ogcgml', 'http://www.opengis.net/ont/gml#')
('ogcsf', 'http://www.opengis.net/ont/sf#')
('orardf', 'http://xmlns.oracle.com/rdf/')
('orageo', 'http://xmlns.oracle.com/rdf/geo/')
('owl',    'http://www.w3.org/2002/07/owl#')
('rdf',    'http://www.w3.org/1999/02/22-rdf-syntax-ns#')
('rdfs',   'http://www.w3.org/2000/01/rdf-schema#')
('xsd',    'http://www.w3.org/2001/XMLSchema#')

これらのデフォルトを上書きするには、aliases属性でnamespace_id値および異なるnamespace_val値を指定します。

filter属性では、追加の選択基準を指定します。この属性がNULLではない場合、WHEREキーワードのないWHERE句の形式で文字列を指定する必要があります。たとえば、この項で前に示したトリプル・パターンの例で'(h >= ''6'')'と指定すると、身長が6以上である祖父の孫に検索結果を絞り込めます。

注意:

filter属性を使用するかわりに、できるかぎり問合せパターン内でFILTERキーワードを使用してください(「グラフ・パターン: 中カッコの構文とOPTIONAL、FILTER、UNIONおよびGRAPHキーワードのサポート」を参照)。FILTERキーワードを使用すると、内部が最適化されるため、パフォーマンスが向上する傾向があります。ただし、FILTERキーワードで表現できないSQL構成要素が必要な場合は、filter引数が便利です。

index_status属性では、関連する伴意のステータスが無効の場合でも、セマンティク・データを問い合せることができます。(仮想モデルを問い合せる場合、この属性は、その仮想モデルに関連付けられた伴意を参照します。)この属性がnullの場合、伴意のステータスが無効だと、問合せによりエラーが戻されます。この属性がNULLではない場合、文字列INCOMPLETEまたはINVALIDを指定する必要があります。異なるindex_status値を持つ問合せの動作については、「不完全な伴意または無効な伴意を使用した問合せの実行」の説明を参照してください。

options属性は、問合せの結果に影響を与えることのできるオプションを指定します。オプションは、キーワードと値のペアで表記します。次のオプションがサポートされています。

  • ALL_AJ_HASHALL_AJ_MERGEおよびALL_BGP_NLは、グローバル問合せオプティマイザ・ヒントです。これにより、指定された結合タイプが、NOT EXISTS演算子およびMINUS演算子に対するすべての反結合で使用されることになります。

  • ALL_BGP_HASHおよびALL_BGP_NLは、すべてのBGP間の結合(ルートBGPとOPTIONAL BGPの間の結合など)で指定の結合タイプを使用する必要があることを示すグローバル問合せオプティマイザ・ヒントです。(BGPは、basic graph patternの略語です)。W3C勧告の「SPARQL Query Language for RDF」の説明では、「SPARQLのグラフ・パターン照合は、基本グラフ・パターンの照合結果を組み合せるという観点で定義されています。単一の基本グラフ・パターンは、フィルタの割込がある一連のトリプル・パターンによって形成されます。任意のグラフ・パターンによって、基本グラフ・パターンが終了します」と記述されています。

    BGP_JOIN(USE_NL)およびBGP_JOIN(USE_HASH) HINT0問合せオプティマイザ・ヒントを使用して、結合タイプをきめ細かく制御できます。

    例1-14に、SEM_MATCH問合せで使用されるALL_BGP_HASHオプションを示します。

  • ALL_LINK_HASHおよびALL_LINK_NLは、すべてのRDF_LINK$結合(BGP内のトリプル・パターン間のすべての結合)の結合タイプを指定するグローバル問合せオプティマイザ・ヒントです。ALL_LINK_HASHALL_LINK_NLも、きめ細かい制御のためにHINT0問合せオプティマイザ内で使用できます。

  • ALL_MAX_PP_DEPTH(n)はグローバル問合せオプティマイザ・ヒントです。これは、プロパティ・パス演算子*と+の評価に使用する最大深度を設定します。デフォルト値は10です。MAX_PP_DEPTH(n) HINT0ヒントは、さらに細かく最大深度を指定するために使用できます。

  • ALL_ORDEREDは、問合せ内の各BGPのトリプル・パターンが順番に評価される必要があることを指定するグローバル問合せオプティマイザ・ヒントです。

    例1-14に、SEM_MATCH問合せで使用されるALL_ORDEREDオプションを示します。

  • ALL_USE_PP_HASHおよびALL_USE_PP_NLは、プロパティ・パス表現の評価に使用する結合タイプを指定するグローバル問合せオプティマイザ・ヒントです。USE_PP_HASHおよびUSE_PP_NL HINT0ヒントは、結合タイプをさらにきめ細かく指定するために使用できます。

  • ALLOW_DUP=Tは、セマンティク・モデルと推論データ(適用可能な場合)のUNIONではなくUNION ALLを実行する、基礎となるSQL文を生成します。このオプションを使用した場合、結果セットに追加の行(重複するトリプル)が生成されるために、それに応じてアプリケーション・ロジックを調整する必要があることがあります。このオプションを指定しない場合、すべてのモデルと推論データにわたって、重複するトリプルは自動的に削除され、マージされたRDFグラフの設定済セマンティクが保持されます。ただし、重複するトリプルを削除すると、問合せの処理時間が長くなります。一般に、1つのSEM_MATCH問合せに複数のセマンティク・モデルが関連している場合、'ALLOW_DUP=T'を指定することで、パフォーマンスが大幅に向上します。

    仮想モデルを問い合せる場合、ALLOW_DUP=Tを指定すると、SEMV_vm_nameビューが問い合せられます。指定しない場合、SEMU_vm_nameビューが問い合せられます。

  • ALLOW_PP_DUP=Tは、+および*プロパティ・パス問合せで結果の重複を許可します。結果の重複が認められると、最初の結果行が早く戻されます。

  • AS_OF [SCN, <SCN_VALUE>]は、指定したSCN時点におけるセマンティク・ネットワークの状態の問合せに、フラッシュバック問合せ使用しなければならないことを示すものです。ここで、<SCN_VALUE>は、有効なシステム変更番号です。

  • AS_OF [TIMESTAMP, <TIMESTAMP_VALUE>]は、指定したタイムスタンプ時点におけるセマンティク・ネットワークの状態の問合せに、フラッシュバック問合せ使用しなければならないことを示すものです。ここで、<TIMESTAMP_VALUE>は、「YYYY/MM/DD HH24:MI:SS.FF」の形式を持つ有効なタイムスタンプ文字列です。

  • CLOB_AGG_SUPPORT=Tは、集計(MIN、MAX、GROUP_CONCAT、SAMPLE)でCLOB値のサポートを有効にします。CLOBサポートを有効化するとパフォーマンスが大幅に低下することに注意してください。

  • CLOB_EXP_SUPPORT=Tは、一部の組込みSPARQL関数でのCLOB値のサポートを有効にします。CLOBサポートを有効化するとパフォーマンスが大幅に低下することに注意してください。

  • CONSTRUCT_STRICT=Tは、SPARQL CONSTRUCTまたはSPARQL DESCRIBE構文の問合せの結果から無効なRDFトリプルを消去します。主語の位置にリテラルがあるRDFトリプル、または述語の位置にリテラルか空白ノードがあるRDFトリプルは無効とみなされます。

  • CONSTRUCT_UNIQUE=Tは、SPARQL CONSTRUCTまたはSPARQL DESCRIBE構文の問合せの結果から重複RDFトリプルを消去します。

  • DISABLE_NULL_EXPR_JOINは、すべてのSELECT式について、NULLでない出力を生成するものとして処理するよう、コンパイラに対し指定するものです。

  • DO_UNESCAPE=Tは、返却列のvar、var$_PREFIX、var$_SUFFIX、var$RDFCLOB、var$RDFLTYP、var$RDFLANGおよびvar$RDFTERMの文字を、W3CのN-Triples仕様(http://www.w3.org/TR/rdf-testcases/#ntriples)に従ってエスケープしません。

    SEM_APIS.ESCAPE_CLOB_TERMSEM_APIS.ESCAPE_CLOB_VALUESEM_APIS.ESCAPE_RDF_TERMSEM_APIS.ESCAPE_RDF_VALUESEM_APIS.UNESCAPE_CLOB_TERMSEM_APIS.UNESCAPE_CLOB_VALUESEM_APIS.UNESCAPE_RDF_TERMおよびSEM_APIS.UNESCAPE_RDF_VALUEのリファレンス情報も参照してください。

  • FINAL_VALUE_HASHおよびFINAL_VALUE_NLは、FILTER句で使用されていない問合せ変数の字句の値を取得するために、使用する必要がある結合メソッドを指定するグローバル問合せオプティマイザ・ヒントです。

  • GRAPH_MATCH_UNNAMED=Tを使用すると、名前なしトリプル(null G_ID)をGRAPH句内で照合可能になります。つまり、グラフが等しい場合、またはグラフの一方または両方がnullの場合、2つのトリプルはグラフ結合条件を満たすことになります。データセットに名前なしTBOXトリプルまたは名前なし伴意トリプルが含まれている場合に、このオプションが役立つことがあります。

  • HINT0={<hint-string>}(発音および表記は"hint (ヒント)"と数字のゼロ)は、1つ以上のキーワードを、問合せの実行計画および結果に影響を与えるヒントとともに指定します。概念的には、n個のトリプル・パターンを持つグラフ・パターンで、m個の固有の変数を参照した場合、(n+m)方向の結合となります。つまり、ターゲットRDFモデルおよび対応する伴意(オプション)のn方向の自己結合が実行された後、値からm個の変数を検索するために、RDF_VALUE$でm個の結合が実行されます。ヒント指定は、問合せ実行で使用される結合順序と結合タイプに影響を与えます。

    ヒント指定<hint-string>では、キーワードを使用します。一部のキーワードは、問合せで使用される各トリプル・パターンおよび変数ごとに、一連(一群)の別名または参照で構成されるパラメータを持ちます。トリプル・パターンの別名の形式は、tiです。iは、問合せ内のトリプル・パターンの0から始まる序数です。たとえば、問合せ内の最初のトリプル・パターンの別名はt0で、2番目のトリプル・パターンの別名はt1、...のようになります。問合せで使用される変数の別名は単に、その変数の名前です。このため、ヒント指定では、グラフ・パターンで使用される変数?xの別名として?xが使用されます。

    問合せの実行計画に影響を与えるために使用するヒントには、LEADING(<sequence of aliases>)、USE_NL(<set of aliases>)、USE_HASH(<set of aliases>)およびINDEX(<alias> <index_name>)があります。これらのヒントの書式と基本的な意味は、SQL文のヒントと同じです(『Oracle Database SQL言語リファレンス』を参照)。

    例1-10に、SEM_MATCH問合せで使用されるHINT0オプションを示します。

  • HTTP_METHOD=POST_PARは、URLエンコーディング・パラメータ・パスを含むHTTP POSTメソッドをSERVICEリクエストに対して使用する必要があると指定します。リクエストのデフォルト・オプションはHTTP GETメソッドです。SPARQLプロトコルの詳細は、http://www.w3.org/TR/2013/REC-sparql11-protocol-20130321/#protocolを参照してください。

  • INF_ONLY=Tは、指定されたモデルおよびルールベースの伴意グラフのみを問い合せます。

  • OVERLOADED_NL=Tは、過負荷のSERVICE句に対し、ネストした手続き型ループによる実行が必要であることを指定するものです。

  • PLUS_RDFT=Tは、SPARQL SELECT構文(「SELECT句の式」を参照)で、射影される各問合せ変数のvar$RDFTERM CLOB列を追加で返す場合に使用できます。この列の値は、SEM_APIS.COMPOSE_RDF_TERM(var, var$RDFVTYP, var$RDFLTYP, var$RDFLANG, var$RDFCLOB)の結果と同等です。このオプションを使用する場合、各変数varの戻り列は、varvar$RDFVID、var$_PREFIX、var$_SUFFIX、var$RDFVTYP、var$RDFCLOB、var$RDFLTYP、var$RDFLANGおよびvar$RDFTERMになります。

  • PLUS_RDFT=VCは、SPARQL SELECT構文(「SELECT句の式」を参照)で、射影される各問合せ変数のvar$RDFTERM VARCHAR2(4000)列を追加で返す場合に使用できます。この列の値は、SEM_APIS.COMPOSE_RDF_TERM(var, var$RDFVTYP, var$RDFLTYP, var$RDFLANG)の結果と同等です。このオプションを使用する場合、各変数varの戻り列は、var、var$RDFVID、var$_PREFIX、var$_SUFFIX、var$RDFVTYP、var$RDFCLOB、var$RDFLTYP、var$RDFLANGおよびvar$RDFTERMになります。

  • PROJ_EXACT_VALUES=Tは、関数から返される値と、値割当て文で使用される定数値の正規化を無効にします。これらの値はデフォルトでは正規化されます。

  • SERVICE_CLOB=Fは、サービスをコールするときにvar$RDFCLOBの列値を保存するかわりに値にnullを設定します。CLOBデータがアプリケーションで必要ない場合、このオプションを使用してCLOB処理を省略するとパフォーマンスを向上させることができます。

  • SERVICE_ESCAPE=Fは、SPARQL SERVICEコールから返されるRDFリテラル値の文字のエスケープを無効にします。RDFリテラル値はデフォルトではエスケープされます。文字のエスケープがアプリケーションに関係ない場合は、文字のエスケープを無効にするとパフォーマンスを向上させることができます。

  • SERVICE_JPDWN=Tは、SPARQL SERVICEでネステッド・ループ結合を使用するための問合せオプティマイザ・ヒントです。例1-70に、SEM_MATCH問合せで使用されるSERVICE_JPDWN=Tオプションを示します。

  • SERVICE_PROXY=<proxy-string>は、http接続を実行するときに使用されるプロキシ・アドレスを設定します。指定したproxy-stringがSERVICE問合せで使用されます。例1-73に、プロキシ・アドレスを含むSEM_MATCH問合せを示します。

  • STRICT_AGG_CARD=Tは、一致しなかったグラフ・パターンを含む集計問合せで、SPARQLセマンティク(1つのnull行)をSQLセマンティク(0行)のかわりに使用します。このオプションによってパフォーマンスがわずかに低下します。

  • STRICT_DEFAULT=Tは、データセット情報が指定されない場合に、デフォルト・グラフを名前なしトリプルに制限します。

graphs属性は、SEM_MACH問合せ用のデフォルト・グラフの構築元となる、名前付きグラフのセットを指定します。そのデータ型はSEM_GRAPHSで、TABLE OF VARCHAR2(4000)という定義を持ちます。この属性のデフォルト値はNULLです。graphsNULLの場合、問合せモデルのセット内のすべてのグラフのすべての和集合が、デフォルト・グラフとして使用されます。

named_graphs属性は、GRAPH句で照合可能な名前付きグラフのセットを指定します。そのデータ型はSEM_GRAPHSで、TABLE OF VARCHAR2(4000)という定義を持ちます。この属性のデフォルト値はNULLです。named_graphsがNULLの場合、問合せモデルのセット内のすべての名前付きグラフを、GRAPH句によって照合することができます。

SEM_MATCH表関数では、入力変数に応じた要素とともにANYDATASET型のオブジェクトが戻されます。次の説明において、varは問合せで使用される変数名を示します。変数varごとに、結果要素にはvarvar$RDFVID、var$_PREFIX、var$_SUFFIX、var$RDFVTYP、var$RDFCLOB、var$RDFLTYPおよびvar$RDFLANGの各属性が含まれます。

このような場合、varはその変数にバインドされた字句の値を保持し、var$RDFVIDは変数にバインドされた値のVALUE_IDを持ちます。var$_PREFIXおよびvar$_SUFFIXは、変数にバインドされた値の接頭辞接尾辞です。var$RDFVTYPは、変数にバインドされた値のタイプ(URILIT [literal]またはBLN [blank node])を示します。var$RDFCLOBは、値がロング・リテラルの場合に変数にバインドされた字句の値を持ちます。var$RDFLTYPは、リテラルがバインドされている場合にそのバインドされたリテラルのタイプを示します。var$RDFLANGは、言語タグ付きのリテラルがバインドされている場合に、そのバインドされたリテラルの言語タグを持ちます。var$RDFCLOBはCLOB型ですが、他のすべての属性はVARCHAR2型です。

リテラル値または空白ノードの場合、接頭辞は値そのものになり、接尾辞はNULLになります。URI値の場合、接頭辞は値の一番右側にある/(スラッシュ)、#(ポンド)または:(コロン)の3つのいずれかの文字から左側の部分となり、接尾辞はそれより右側の値部分となります。たとえば、URI値http://www.example.org/family/grandParentOfの場合、接頭辞はhttp://www.example.org/family/、接尾辞はgrandParentOfとなります。

変数値の列とともに、SPARQL SELECT構文を使用するSEM_MATCH問合せは、追加のNUMBER列であるSEM$ROWNUMを戻します(この列は、SPARQL ORDER BY句を含む問合せの正しい結果順序を保証するために使用できます)。

SPARQL ASK構文を使用するSEM_MATCH問合せは、列ASK、ASK$RDFVID、ASK$_PREFIX、ASK$_SUFFIX、ASK$RDFVTYP、ASK$RDFCLOB、ASK$RDFLTYP、ASK$RDFLANGおよびSEM$ROWNUMを返します。これは、1つの?ask変数を射影するSPARQL SELECT構文の問合せと同じです。

SPARQL CONSTRUCTまたはSPARQL DESCRIBE構文を使用するSEM_MATCH問合せは、問合せ結果バインディングではなくRDFトリプル・データを含む列を返します。これらの問合せは、主語、述語および目的語のコンポーネントについて値を返します。詳細は、「グラフ・パターン: SPARQL CONSTRUCT構文のサポート」を参照してください。

SEM_RELATED演算子を使用してOWLオントロジを問い合せる方法の詳細は、「セマンティク演算子を使用したリレーショナル・データの問合せ」を参照してください。

複数のモデルを問い合せる場合、または1つ以上のモデルおよびそれに対応する伴意を問い合せる場合、パフォーマンスの向上のため、仮想モデルを使用することを考慮してください(「仮想モデル」を参照)。

例1-9 SEM_MATCH表関数

例1-9では、RDFSfamily_rbの2つのルールベースによる推論を使用して、familyモデルからすべての祖父(祖父母の男性の方)とその孫を選択します。((この例は、 「例: 家系の情報」例1-110の抜粋です。)

SELECT x grandfather, y grandchild
  FROM TABLE(SEM_MATCH(
    '{?x :grandParentOf ?y . ?x rdf:type :Male}',
    SEM_Models('family'),
    SEM_Rulebases('RDFS','family_rb'), 
    SEM_ALIASES(SEM_ALIAS('','http://www.example.org/family/')),
    null));

例1-10 SEM_MATCH表関数を使用したHINT0オプション

例1-10例1-9と同じ機能ですが、HINT0オプションが追加されています。

SELECT x grandfather, y grandchild
  FROM TABLE(SEM_MATCH(
    '{?x :grandParentOf ?y . ?x rdf:type :Male}',
    SEM_Models('family'),
    SEM_Rulebases('RDFS','family_rb'), 
    SEM_Aliases(SEM_ALIAS('','http://www.example.org/family/')),
    null,
    null,
    'HINT0={LEADING(t0 t1) USE_NL(?x ?y) GET_CANON_VALUE(?x ?y)}'));

例1-11 SEM_MATCH表関数

例1-11では、Pathway/Genome BioPaxオントロジを使用して、ProteinsComplexesの両方に属するすべての化学的複合タイプを取得します。

SELECT t.r 
  FROM TABLE (SEM_MATCH ( 
      '{?r rdfs:subClassOf :Proteins .  
        ?r rdfs:subClassOf :Complexes}', 
      SEM_Models ('BioPax'), 
      SEM_Rulebases ('rdfs'), 
      SEM_Aliases (SEM_ALIAS('', 'http://www.biopax.org/release1/biopax-release1.owl')),
      NULL)) t;

例1-11のとおり、SEM_MATCH表関数の検索パターンは、変数が疑問符文字(?)で始まるSPARQLに似た構文を使用して指定します。この例の場合、変数?rは、同じ語に一致する必要があるため、ProteinsComplexesの両方のサブクラスである必要があります。

1.6.1 不完全または無効な伴意による問合せの実行

関連する伴意のステータスが無効の場合でも、SEM_MATCH表関数のindex_status属性に文字列値INCOMPLETEまたはINVALIDを指定すると、セマンティク・データを問い合せることができます。(伴意のステータスは、「伴意(ルール索引)」に記載されているとおり、MDSYS.SEM_RULES_INDEX_INFOビューのSTATUS列に格納されます。)(SEM_MATCH表関数については、「SEM_MATCH表関数を使用したセマンティク・データの問合せ」を参照してください。)

index_status属性の値は、問合せの動作に次のように影響します。

  • 伴意のステータスが有効の場合、問合せ動作はindex_status属性の値に影響を受けません。

  • index_statusに値を指定しないか、NULL値を指定した場合に、伴意のステータスが無効だと、問合せからエラーが戻されます。

  • index_status属性に文字列INCOMPLETEを指定すると、伴意のステータスが不完全または有効である場合、問合せが実行されます。

  • index_status属性に文字列INVALIDを指定すると、伴意の実際のステータス(無効、不完全または有効)にかかわらず問合せが実行されます。

ただし、伴意のステータスが不完全または無効の場合、次の考慮事項が適用されます。

  • ステータスが不完全の場合、基礎となるモデルに最近挿入されて推論可能となったいくつかのトリプルは、実際には伴意に存在しないことがあり、したがって問合せにより戻される結果は不正確となる可能性があるため、伴意の内容は近似値となる可能性があります。

  • ステータスが無効の場合、基礎となるモデルまたはルールベース(あるいはその両方)が最近変更されて推論不可能となったいくつかのトリプルは、まだ伴意に存在することがあり、したがって問合せにより戻される結果の正確性が影響を受ける可能性があるため、伴意の内容は近似値となる可能性があります。推論不可能となったトリプルが存在する可能性に加え、一部の推論可能な行が実際には伴意に存在しない可能性もあります。

1.6.2 グラフ・パターン: 中カッコの構文とOPTIONAL、FILTER、UNIONおよびGRAPHキーワードのサポート

SEM_MATCH表関数は、一連のトリプル・パターンを中カッコで囲むグラフ・パターンの構文を受け入れます。OPTIONAL、FILTER、UNIONまたはGRAPHキーワードが続く場合以外は、セパレータとしてピリオドが必要です。この構文では、次の操作を任意に組み合せて実行できます。

  • OPTIONAL構成要素を使用して、部分一致の場合にも結果を取得できます。

  • FILTER構成要素を使用して、ソリューションを問合せに制限するグラフ・パターンのフィルタ式を指定できます。

  • UNION構成要素を使用して、複数の代替グラフ・パターンのいずれかを一致させることができます。

  • GRAPH構成要素(「GRAPHキーワード・サポート」を参照)を使用して、グラフ・パターンの一致範囲を名前付きグラフのセットに制限できます。

算術演算子(+、-、*、/)、ブール演算子と論理連結語(||、&&、!)、および比較演算子(<、>、<=、>=、=、!=)に加えて、いくつかの組込み関数をFILTER句で使用できます。表1-12に、FILTER句で使用できる組込み関数を示します。表1-12の「説明」列で、xyおよびzは、適切な型の引数です。

表1-12 FILTER句で使用できる組込み関数

関数 説明

ABS(RDF term)

termの絶対値を戻します。termが数値以外の場合は、nullを戻します。

BNODE(literal)またはBNODE()

問合せのデータセット内のすべての空白ノード、および他の問合せでこの関数によって作成された空白ノードとは別の空白ノードを構築します。引数を指定しない形式では、すべてのコールで異なる空白ノードが構築されます。単純なリテラルを指定する形式の場合、異なる単純なリテラルに対しては異なる空白ノードが構築され、同じ単純なリテラルを使用したコールでは同じ空白ノードが構築されます。

BOUND(variable)

BOUND(x)は、xが結果でバインドされる場合(つまりnull以外の場合)はtrueを戻し、それ以外の場合はfalseを戻します。

CEIL(RDF term)

term以上の最も近い小数部分なしの数値を戻します。termが数値以外の場合は、nullを戻します。

COALESCE(term list)

エラーが発生せずに評価された引数リストの最初の要素を戻します。評価される場合は、バインドされていない変数でエラーが発生します。有効な要素が語句リストにない場合は、nullを戻します。

CONCAT(term list)

語句リスト内の文字列値を連結した結果のxsd:String値を戻します。

CONTAINS(literal, match)

文字列matchliteral内で検出された場合に、trueを戻します。それ以外の場合はfalseを戻します。

DATATYPE(literal)

DATATYPE(x)は、xのデータ型を表すURIを戻します。

DAY(argument)

引数の日部分に対応する整数を戻します。引数がdateTimeまたはdateデータ型でない場合は、null値を戻します。

ENCODE_FOR_URI(literal)

literal内の予約済文字がエスケープされ、そのパーセントエンコード形式に変換される文字列を戻します。

EXISTS(pattern)

含まれているグループ・グラフ・パターンと現在のアクティブ・グラフ内の現在のバインディングを使用して、パターンが問合せデータセットと一致する場合に、trueを戻します。一致がない場合は、falseを戻します。

FLOOR(RDF term)

termを下回る、最も近い小数部分なしの数を戻します。termが数値以外の場合は、nullを戻します。

HOURS(argument)

argumentの時間部分に対応する整数を戻します。引数がdateTimeまたはdateデータ型でない場合は、null値を戻します。

IF(condition , expression1, expression2)

条件を評価して、有効なブール値を取得します。trueの場合、最初の式が評価され、その値が戻されます。falseの場合、2つ目の式が使用されます。条件でエラーが発生した場合、エラーはIF文の結果として渡されます。

IRI(RDF term)

引数termの文字列表現を解決するIRIを戻します。問合せで定義されているベースIRIがある場合、IRはそれに対して解決され、結果は絶対IRIになる必要があります。

isBLANK(RDF term)

isBLANK(x)は、xが空白ノードの場合にtrueを戻し、それ以外の場合はfalseを戻します。

isIRI(RDF term)

isIRI(x)は、xがIRIの場合にtrueを戻し、それ以外の場合はfalseを戻します。

isLITERAL(RDF term)

isLiteral(x)は、xがリテラルの場合にtrueを戻し、それ以外の場合はfalseを戻します。

IsNUMERIC(RDF term)

termが数値の場合はtrueを戻し、それ以外の場合はfalseを戻します。

isURI(RDF term)

isURI(x)は、xがURIの場合にtrueを戻し、それ以外の場合はfalseを戻します。

LANG(literal)

LANG(x)は、xの言語タグをシリアライズするプレーン・リテラルを戻します。

LANGMATCHES(literal, literal)

LANGMATCHES(x、y)は、言語タグxが言語レンジyと一致する場合にtrueを戻し、それ以外の場合はfalseを戻します。

LCASE(literal)

リテラル内の各文字を対応する子文字に変換して、文字列を戻します。

MD5(literal)

MD5ハッシュ関数に対応する、literalのチェックサムを戻します。

MINUTES(argument)

argumentの分部分に対応する整数を戻します。引数がdateTimeまたはdateデータ型でない場合は、null値を戻します。

MONTH(argument)

argumentの月部分に対応する整数を戻します。引数がdateTimeまたはdateデータ型でない場合は、null値を戻します。

NOT_EXISTS(pattern)

含まれているグループ・グラフ・パターンと現在のアクティブ・グラフ内の現在のバインディングを使用して、パターンが問合せデータセットと一致しない場合に、trueを戻します。それ以外の場合はfalseを戻します。

NOW()

問合せ実行時点の現在の時刻に対応するxsd:dateTime値を戻します。

RAND()

[0,1)のレンジ内の数値を生成します。

REGEX(string, pattern)

REGEX(x,y)は、xが正規表現yに一致する場合にtrueを戻し、それ以外の場合はfalseを戻します。サポートされる正規表現の詳細は、『Oracle Database SQL言語リファレンス』の付録「Oracleの正規表現のサポート」を参照してください。

REGEX(string, pattern, flags)

REGEX (x,y,z)は、xzに指定されたオプションを使用して正規表現yと一致する場合にtrueを戻し、それ以外の場合はfalseを戻します。使用可能なオプション: 's'はドットがすべてに一致するモード('.'は改行文字を含む任意の文字と一致)、'm'は複数行モード('^'は任意の行の先頭と一致し、'$'は任意の行の末尾と一致)、'i'は大/小文字を区別しないモード、'x'は照合前に正規表現から空白文字を削除します。

REPLACE(string, pattern, replacement)

string内の正規表現patternの一致箇所が、それぞれreplacementに置き換えられた文字列を戻します。サポートされる正規表現の詳細は、『Oracle Database SQL言語リファレンス』の付録「Oracleの正規表現のサポート」を参照してください。

REPLACE(string, pattern, replacement, flags)

string内の正規表現patternの一致箇所が、それぞれreplacementに置き換えられた文字列を戻します。使用可能なオプション: 's'はドットがすべてに一致するモード('.'は改行文字を含む任意の文字と一致)、'm'は複数行モード('^'は任意の行の先頭と一致し、'$'は任意の行の末尾と一致)、'i'は大/小文字を区別しないモード、'x'は照合前に正規表現から空白文字を削除します。

サポートされる正規表現の詳細は、『Oracle Database SQL言語リファレンス』の付録「Oracleの正規表現のサポート」を参照してください。

ROUND(RDF term)

termに最も近い小数部分なしの数を戻します。2つの値が存在する場合、正の無限大に近い方の値が戻されます。termが数値以外の場合は、nullを戻します。

sameTerm(RDF term, RDF term)

sameTerm(x, y)は、xおよびyが同じRDF語句の場合にtrueを戻し、それ以外の場合はfalseを戻します。

SECONDS(argument)

argumentの秒部分に対応する整数を戻します。引数がdateTimeまたはdateデータ型でない場合は、null値を戻します。

SHA1(literal)

SHA1ハッシュ関数に対応する、literalのチェックサムを戻します。

SHA256(literal)

SHA256ハッシュ関数に対応する、literalのチェックサムを戻します。

SHA384(literal)

SHA384ハッシュ関数に対応する、literalのチェックサムを戻します。

SHA512(literal)

SHA512ハッシュ関数に対応する、literalのチェックサムを戻します。

STR(RDF term)

STR(x)は、xの文字列表現のプレーン・リテラル(つまり、二重引用符で囲まれた、MDSYS.RDF_VALUE$のVALUE_NAME列に格納される内容)を戻します。

STRAFTER(literal, literal)

StrAfter (x,y)は、x内でyの最初の一致からxの末尾までの部分文字列に対応する文字列部分を戻します。x内にyの一致がない場合は、空の文字列が戻されます。

STRBEFORE(literal, literal)

StrBefore (x,y)は、xの先頭からyの最初の一致までに対応する文字列部分を戻します。x内にyの一致がない場合は、空の文字列が戻されます。

STRDT(string, datatype)

引数として渡されるstring字句形式とdatatypeで構成されるリテラル語句を構築します。datatypeはURIである必要があり、そうでない場合はNULL値を戻します。

STRENDS(literal, match)

文字列literalが文字列matchで終わる場合にtrueを戻します。それ以外の場合はfalseを戻します。

STRLANG (string, languageTag)

引数として渡されたstring字句形式と言語タグから成る文字列を構築します。

STRLEN(literal)

literalの字句形式の長さを戻します。

STRSTARTS(literal, match)

文字列literalが文字列matchで始まる場合に、trueを戻します。それ以外の場合はfalseを戻します。

STRUUID()

新しいUUIDのスキーム・セクションを含む文字列を戻します。

SUBSTR(term, startPos)

startPosからtermの末尾までの、termの部分と対応する文字列を戻します。先頭文字の索引は1です。

SUBSTR(term, startPos, length)

startPosからlength文字までの、termの部分に対応する文字列を戻します。先頭文字の索引は1です。

term IN (term list)

xtermlistの値のいずれかで検出できた場合、式x IN(term list)はtrueを戻します。検出されない場合は、falseを戻します。長さ0のリストは有効です。termlistの値のいずれかでエラーが発生すると、エラーのためxは検出されません。

term NOT IN (term list)

xをterm listの値のいずれかで検出できた場合、式x NOT IN(term list)はfalseを戻します。検出されない場合は、trueを戻します。長さ0のリストは有効です。term listの値のいずれかでエラーが発生すると、エラーのためxは検出されません。

TIMEZONE(argument)

xsd:dayTimeDuration値としてargumentのタイムゾーン・セクションを戻します。引数がdateTimeまたはdateデータ型でない場合は、null値を戻します。

TZ(argument)

argumentのタイムゾーン部分に対応する整数を戻します。引数がdateTimeまたはdateデータ型でない場合は、null値を戻します。

UCASE(literal)

literal内の各文字を対応する大文字に変換して、文字列を戻します。

URI(RDF term)

IRI(RDF term)のシノニム

UUID()

新しいUniversal Unique Identifierを含むURIを戻します。この値およびバージョンは、PL/SQL関数sys_guid ()と対応します。

YEAR(argument)

argumentの年部分に対応する整数を戻します。

SEM_MATCHで使用可能な組込み関数の理解を深めるには、SPARQL問合せ言語指定(http://www.w3.org/TR/sparql11-query/)において定義される組込み関数の説明も参照してください。

さらに、Oracle Databaseの機能を利用したOracle独自の問合せ関数も用意されています。こうした関数は問合せでのパフォーマンス向上に有効です。次の表に、こうしたOracle固有の関数を一覧で示します。なお、組込みの接頭辞orardfは、<http://xmlns.oracle.com/rdf/>に展開されます。

表1-13 Oracle固有の問合せ関数

関数 説明

orardf:like(RDF term, pattern)

指定したtermが、指定したpatternと相似パターン上で合致する場合にtrueを返し、そうでない場合にはfalseを返します。詳細は、「全文検索」を参照してください。

orardf:sameCanonTerm(RDF term, RDF term)

2つのtermが、同じ正規のRDF語句である場合にtrueを返し、そうでない場合にfalseを返します。VALUE_IDに基づく比較ができるため、sameTerm(?x, ?y) or (?x = ?y)よりも効率的です。

orardf:textContains(RDF term, pattern)

指定したtermが、指定したpatternとOracle Text検索パターン上で合致する場合にtrueを返し、そうでない場合にはfalseを返します。詳細は、「全文検索」を参照してください。

orardf:textScore(invocation id)

orardf:textContainsによる照合時のスコアを返します。詳細は、「全文検索」を参照してください。

(組込みの空間関数)

(「空間のサポート」を参照)

次のXMLスキーマをキャストする関数は、FILTER句で使用できます。これらの関数は、RDF語句を入力として取得して必要な型の新しいRDF語句を戻すか、RDF語句を目的の型にキャストできない場合はエラーを発生させます。型キャストの詳細は、XPath問合せの仕様(http://www.w3.org/TR/xpath-functions/#casting-from-primitive-to-primitive)の17.1項を参照してください。これらの関数は、XMLネームスペースxsd : http://www.w3.org/2001/XMLSchema#を使用します。

  • xsd:string (RDF term)

  • xsd:dateTime (RDF term)

  • xsd:boolean (RDF term)

  • xsd:integer (RDF term)

  • xsd:float (RDF term)

  • xsd:double (RDF term)

  • xsd:decimal (RDF term)

中カッコを含む構文を使用してグラフ・パターンを表現した場合、次のようになります。

  • 問合せは常に、変数の一致する値の正規字句形式を戻します。

  • options引数にHINT0={<hint-string>}を使用して指定するヒント(「SEM_MATCH表関数を使用したセマンティク・データの問合せ」を参照)は、ルートBGP内のグラフ・パターン部分に基づいてのみ構築する必要があります。たとえば、例1-13の問合せのヒント指定で使用できる有効な別名は、t0t1?xおよび?yのみです。インライン問合せオプティマイザ・ヒントを使用すると、グラフ・パターンの他の部分に影響を与えることができます(「インライン問合せオプティマイザ・ヒント」を参照)。

  • FILTER構成要素は、ロング・リテラルにバインドされた変数ではサポートされません。

例1-12 中カッコの構文

例1-12は、中カッコとピリオドを含む構文を使用してSEM_MATCH表関数内のグラフ・パターンを表現しています。

SELECT x, y
  FROM TABLE(SEM_MATCH(
    '{?x :grandParentOf ?y . ?x rdf:type :Male}',
    SEM_Models('family'),
    SEM_Rulebases('RDFS','family_rb'), 
    SEM_ALIASES(SEM_ALIAS('','http://www.example.org/family/')),
    null));

例1-13 中カッコの構文およびOPTIONAL構成要素

例1-13では、各祖父の参加する試合の名前(いずれの試合にも参加しない場合はNULL)が戻されるように、OPTIONAL構成要素を使用して例1-12を変更しています。

SELECT x, y, game
  FROM TABLE(SEM_MATCH(
    '{?x :grandParentOf ?y . ?x rdf:type :Male . 
      OPTIONAL{?x :plays ?game} 
     }',
    SEM_Models('family'),
    SEM_Rulebases('RDFS','family_rb'), 
    SEM_ALIASES(SEM_ALIAS('','http://www.example.org/family/')),
    null,
    null,
    'HINT0={LEADING(t0 t1) USE_NL(?x ?y)}'));

例1-14 中カッコの構文および複数パターンのOPTIONAL構成要素

OPTIONALグラフ・パターンに複数のトリプル・パターンが存在すると、オプションの変数の値は、OPTIONALグラフ・パターンの各トリプル・パターンに一致が検出された場合のみ戻されます。例1-14例1-13を変更したもので、祖父ごとに、祖父と孫の両方が参加する試合の名前、または祖父と孫に共通の試合がない場合はnullが戻されるようになっています。ここでは、グローバル問合せオプティマイザ・ヒントも使用して、トリプル・パターンが各BGP内で順番に評価される必要があること、およびルートBGPをOPTIONAL BGPと結合するためにハッシュ結合を使用する必要があることを指定しています。

SELECT x, y, game
  FROM TABLE(SEM_MATCH(
    '{?x :grandParentOf ?y . ?x rdf:type :Male . 
      OPTIONAL{?x :plays ?game . ?y :plays ?game} 
     }',
    SEM_Models('family'),
    SEM_Rulebases('RDFS','family_rb'), 
    SEM_ALIASES(SEM_ALIAS('','http://www.example.org/family/')),
    null,
    'ALL_ORDERED ALL_BGP_HASH'));

例1-15 中カッコの構文およびネストしたOPTIONAL構成要素

単一の問合せに複数のOPTIONALグラフ・パターンを含むことが可能であり、ネスト化またはパラレル化することもできます。例1-15は、例1-14を変更してOPTIONALグラフ・パターンをネスト化したものです。この例では、祖父ごとに、(1)祖父が参加した試合、または祖父が試合に参加しなかった場合はnullを戻し、(2)祖父が試合に参加した場合は同じ試合に参加した孫の年齢、または孫と共通の試合がなかった場合はnullを戻します。例1-15では、ネストされたOPTIONALグラフ・パターン「?y :plays ?game . ?y :age ?age」が一致しない場合でも、?gameに対して値が戻される点に注意してください。

SELECT x, y, game, age
  FROM TABLE(SEM_MATCH(
    '{?x :grandParentOf ?y . ?x rdf:type :Male . 
      OPTIONAL{?x :plays ?game 
                          OPTIONAL {?y :plays ?game . ?y :age ?age} } 
     }',
    SEM_Models('family'),
    SEM_Rulebases('RDFS','family_rb'), 
    SEM_ALIASES(SEM_ALIAS('','http://www.example.org/family/')),
    null));

例1-16 中カッコの構文およびパラレルのOPTIONAL構成要素

例1-16では、パラレルのOPTIONALグラフ・パターンを使用して例1-14を変更しています。この例では、各祖父について、(1)祖父の参加する試合(いずれの試合にも参加しない場合はNULL)、および(2)祖父の電子メール・アドレス(電子メール・アドレスがない場合はNULL)が戻されます。ネストしたOPTIONALグラフ・パターンとは異なり、パラレルのOPTIONALグラフ・パターンはそれぞれ個別に処理されます。つまり、電子メール・アドレスが見つかると、それは試合が見つかったかどうかにかかわらず戻され、試合が見つかると、それは電子メール・アドレスが見つかったかどうかにかかわらず戻されます。

SELECT x, y, game, email
  FROM TABLE(SEM_MATCH(
    '{?x :grandParentOf ?y . ?x rdf:type :Male . 
      OPTIONAL{?x :plays ?game}
      OPTIONAL{?x :email ?email} 
     }',
    SEM_Models('family'),
    SEM_Rulebases('RDFS','family_rb'), 
    SEM_ALIASES(SEM_ALIAS('','http://www.example.org/family/')),
    null));

例1-17 中カッコの構文およびFILTER構成要素

例1-17では、NYまたはCAに居住している祖父のみの孫の情報が戻されるように、FILTER構成要素を使用して例1-12を変更しています。

SELECT x, y
  FROM TABLE(SEM_MATCH(
    '{?x :grandParentOf ?y . ?x rdf:type :Male . ?x :residentOf ?z
       FILTER (?z = "NY"  || ?z = "CA")}',
    SEM_Models('family'),
    SEM_Rulebases('RDFS','family_rb'), 
    SEM_ALIASES(SEM_ALIAS('','http://www.example.org/family/')),
    null));

例1-18 中カッコの構文とREGEXおよびSTR組込み関数を使用したFILTER構成要素

例1-18では、REGEX組込み関数を使用して、Oracle電子メール・アドレスを持つすべての祖父を選択しています。正規表現パターン内のバックスラッシュ(\)文字は、問合せ文字列内でエスケープする必要があります(たとえば\\.はパターン\.となります)。

SELECT x, y, z
  FROM TABLE(SEM_MATCH(
    '{?x :grandParentOf ?y . ?x rdf:type :Male . ?x :email ?z
       FILTER (REGEX(STR(?z), "@oracle\\.com$"))}',
    SEM_Models('family'),
    SEM_Rulebases('RDFS','family_rb'), 
    SEM_ALIASES(SEM_ALIAS('','http://www.example.org/family/')),
    null));

例1-19 中カッコの構文とUNIONおよびFILTER構成要素

例1-19では、祖父がNYまたはCAに居住しているか、NYまたはCAに不動産を所有している場合にのみ、あるいは両方の条件がtrueの場合(祖父がNYまたはCAに居住し、かつ不動産を所有している場合)に祖父が戻されるように、UNION構成要素を使用して例1-17を変更しています。

SELECT x, y
  FROM TABLE(SEM_MATCH(
    '{?x :grandParentOf ?y . ?x rdf:type :Male 
       {{?x :residentOf ?z} UNION {?x :ownsPropertyIn ?z}}
       FILTER (?z = "NY"  || ?z = "CA")}',
    SEM_Models('family'),
    SEM_Rulebases('RDFS','family_rb'), 
    SEM_ALIASES(SEM_ALIAS('','http://www.example.org/family/')),
    null));
1.6.2.1 GRAPHキーワード・サポート

SEM_MATCH問合せは、RDFデータセットに対して実行されます。RDFデータセットは、1つの名前なしグラフ(デフォルト・グラフ)および1つ以上の名前付きグラフを含むグラフのコレクションです(URIで識別されます)。GRAPH句に出現するグラフ・パターンは名前付きグラフのセットに対して照合され、GRAPH句に出現しないグラフ・パターンはデフォルト・グラフに対して照合されます。graphsおよびnamed_graphs SEM_MATCHパラメータは、SEM_MATCH問合せに対してデフォルト・グラフおよび名前付きグラフのセットを構築するために使用されます。可能なデータセットの構成を、表1-14にまとめます。

表1-14 SEM_MATCHのgraphsとnamed_graphsの値、および結果のデータセット構成

パラメータの値 デフォルトのグラフ 名前付きグラフのセット

graphs: NULL

named_graphs: NULL

すべての名前なしトリプルと、すべての名前付きグラフ・トリプルのすべての和集合。(ただし、optionsパラメータにSTRICT_DEFAULT=Tが含まれる場合は、名前なしトリプルのみがデフォルト・グラフに含められます。)

すべての名前付きグラフ

graphs: NULL

named_graphs: {g1,…, gn}

空のセット

{g1,…, gn}

graphs: {g1,…, gm}

named_graphs: NULL

{g1,…, gm}のUNION ALL

空のセット

graphs: {g1,…, gm}

named_graphs: {gn,…, gz}

{g1,…, gm}のUNION ALL

{gn,…, gz}

RDFデータセットとGRAPH構成要素の詳細は、W3C SPARQL仕様、特にhttp://www.w3.org/TR/rdf-sparql-query/#rdfDatasetも参照してください。

例1-20 名前付きグラフの構成要素

例1-20では、GRAPH構成要素を使用して、グラフ・パターン照合の範囲を特定の名前付きグラフに指定しています。この例では、<http://www.example.org/family/Smith>名前付きグラフで、すべての人の名前および電子メール・アドレスを検出します。

SELECT name, email
  FROM TABLE(SEM_MATCH(
    '{GRAPH :Smith {
       ?x :name ?name . ?x :email ?email } }',
    SEM_Models('family'),
    SEM_Rulebases('RDFS','family_rb'), 
    SEM_ALIASES(SEM_ALIAS('','http://www.example.org/family/')),
    null));

例1-21 named_graphsパラメータの使用

URIの他に、GRAPHキーワードの後に変数を使用できます。例1-21では、GRAPHキーワードとともに変数?gを使用し、named_graphsパラメータを使用して、?gの可能な値を、<http://www.example.org/family/Smith>および<http://www.example.org/family/Jones>名前付きグラフに制限しています。SEM_ALIASES引数で指定される別名は、graphsおよびnamed_graphsパラメータで使用できます。

SELECT name, email
  FROM TABLE(SEM_MATCH(
    '{GRAPH ?g {
       ?x :name ?name . ?x :email ?email } }',
    SEM_Models('family'),
    SEM_Rulebases('RDFS','family_rb'), 
    SEM_ALIASES(SEM_ALIAS('','http://www.example.org/family/')),
    null,null,null,null,
    SEM_GRAPHS('<http://www.example.org/family/Smith>',
               ':Jones')));

例1-22 graphsパラメータの使用

例1-22では、デフォルト・グラフを使用して、<http://www.example.org/family/Smith><http://www.example.org/family/Jones>名前付きグラフの和集合を問い合せています。

FROM TABLE(SEM_MATCH(
    '{?x :name ?name . ?x :email ?email }',
    SEM_Models('family'),
    SEM_Rulebases('RDFS','family_rb'), 
    SEM_ALIASES(SEM_ALIAS('','http://www.example.org/family/')),
    null,null,null,
    SEM_GRAPHS('<http://www.example.org/family/Smith>', 
               ':Jones'),
    null));

1.6.3 グラフ・パターン: SPARQL ASK構文のサポート

SEM_MATCHでは、問合せパラメータに完全指定のSPARQL ASK問合せを使用できます。

ASK問合せは、指定の問合せパターンに対する解が存在するかどうかをテストするために使用されます。他の形式のSPARQL問合せとは異なり、ASK問合せでは問合せパターンの解に関する情報は返されません。かわりに、解が存在する場合は"true"^^xsd:boolean、解が存在しない場合は"false"^^xsd:booleanが返されます。

すべてのSPARQL ASK問合せは同じ列(ASK、ASK$RDFVID、ASK$_PREFIX、ASK$_SUFFIX、ASK$RDFVTYP、ASK$RDFCLOB、ASK$RDFLTYP、ASK$RDFLANG、SEM$ROWNUM)を返します。これらの列は、1つの?ask変数を射影するSPARQL SELECT構文の問合せと同じであることに注意してください。

SPARQL ASK問合せは、同等のSPARQL SELECT構文の問合せよりもパフォーマンスが高くなります。ASK問合せは、問合せ変数の字句の値を取得する必要がなく、1つの結果が見つかると問合せの実行を停止できるためです。

SPARQL ASK問合せはSPARQL SELECT問合せと同じ構文を使用しますが、最上位のSELECT句をキーワードASKで置き換える必要があります。

例1-23 SPARQL ASK

例1-23に、10メガ・ピクセル超で50ドル未満のカメラが売り出されているかどうかを判別するSPARQL ASK問合せを示します。

SELECT ask
  FROM TABLE(SEM_MATCH(
    'PREFIX : <http://www.example.org/electronics/> 
     ASK
     WHERE
      {?x :price ?p .
       ?x :megapixels ?m .
       FILTER (?p < 50 && ?m > 10)
      }',
    SEM_Models('electronics'),
    SEM_Rulebases('RDFS'), 
    null, null));

SPARQL ASK問合せの詳細は、W3C SPARQL仕様、特にhttp://www.w3.org/TR/sparql11-query/#askも参照してください。

1.6.4 グラフ・パターン: SPARQL CONSTRUCT構文のサポート

SEM_MATCHでは、問合せパラメータに完全指定のSPARQL CONSTRUCT問合せを使用できます。

CONSTRUCT問合せは、格納されているRDFデータからRDFグラフを構築するために使用されます。SPARQL SELECT問合せとは対照的に、CONSTRUCT問合せは問合せの解(変数バインディング)のセットではなくRDFトリプルのセットを返します。

すべてのSPARQL CONSTRUCT問合せは、SEM_MATCHから同じ列を返します。これらの列は、RDFトリプルの主語、述語および目的語に対応し、トリプルの構成要素ごとに10個の列があります。この他にSEM$ROWNUM列も返されます。具体的には返される列は次のとおりです。

SUBJ
SUBJ$RDFVID
SUBJ$_PREFIX
SUBJ$_SUFFIX
SUBJ$RDFVTYP
SUBJ$RDFCLOB
SUBJ$RDFLTYP
SUBJ$RDFLANG
SUBJ$RDFTERM
SUBJ$RDFCLBT
PRED
PRED$RDFVID
PRED$_PREFIX
PRED$_SUFFIX
PRED$RDFVTYP
PRED$RDFCLOB
PRED$RDFLTYP
PRED$RDFLANG
PRED$RDFTERM
PRED$RDFCLBT
OBJ
OBJ$RDFVID
OBJ$_PREFIX
OBJ$_SUFFIX
OBJ$RDFVTYP
OBJ$RDFCLOB
OBJ$RDFLTYP
OBJ$RDFLANG
OBJ$RDFTERM
OBJ$RDFCLBT
SEM$ROWNUM

各コンポーネントで、COMP、COMP$RDFVID、COMP$_PREFIX、COMP$_SUFFIX、COMP$RDFVTYP、COMP$RDFCLOB、COMP$RDFLTYPおよびCOMP$RDFLANGは、SPARQL SELECT問合せの同じ列の値に対応します。COMP$RDFTERMはN-Triple構文のVARCHAR2(4000) RDF語句を保持し、COMP$RDFCLBTはN-Triple構文のCLOB RDF語句を保持します。

SPARQL CONSTRUCT問合せはSPARQL SELECT問合せと同じ構文を使用しますが、最上位のSELECT句をCONSTRUCTテンプレートで置き換えます。CONSTRUCTテンプレートは、WHERE句に定義された問合せパターンの結果を使用して結果のRDFグラフの作成方法を決定します。CONSTRUCTテンプレートでは、キーワードCONSTRUCTの後に、中カッコで囲まれた一連のSPARQLトリプル・パターンが続きます。キーワードOPTIONAL、UNION、FILTER、MINUS、BIND、VALUESおよびGRAPHは、CONSTRUCTテンプレートでは使用できません。プロパティ・パス表現もCONSTRUCTテンプレート内で使用できません。ただし、WHERE句内の問合せパターンではこれらのキーワードを使用できます。

SPARQL CONSTRUCT問合せは、次の方法で結果のRDFグラフを構築します。WHERE句から返される結果行ごとに、変数値がCONSTRUCTテンプレートに代入され、1つ以上のRDFトリプルが作成されます。例1-24のWHERE句のグラフ・パターンが次の結果行を返すとします。

E$RDFTERM FNAME$RDFTERM LNAME$RDFTERM

ent:employee1

"Fred"

"Smith"

ent:employee2

"Jane"

"Brown"

ent:employee3

"Bill"

"Jones"

例1-24のSEM_MATCH CONSTRUCT問合せ全体は、6個のRDFトリプルに対応する次の行を返します(問合せパターンの結果行ごとに2個ずつ)。

SUBJ$RDFTERM PRED$RDFTERM OBJ$RDFTERM

ent:employee1

foaf:givenName

"Fred"

ent:employee1

foaf:familyName

"Smith"

ent:employee2

foaf:givenName

"Jane"

ent:employee2

foaf:familyName

"Brown"

ent:employee3

foaf:givenName

"Bill"

ent:employee3

foaf:familyName

"Jones"

SPARQL CONSTRUCTの動作に影響を与えるSEM_MATCH問合せオプションが2つあります。CONSTRUCT_UNIQUE=TおよびCONSTRUCT_STRICT=Tです。CONSTRUCT_UNIQUE=T問合せオプションを使用すると、CONSTRUCT問合せから一意のRDFトリプルのみが返されます。 CONSTRUCT_STRICT=T問合せオプションを使用すると、CONSTRUCT問合せから有効なRDFトリプルのみが返されます。有効なRDFトリプルは、主語の位置にURIまたは空白ノードがあり(1)、述語の位置にURIがあり(2)、目的語の位置にURI、空白ノードまたはRDFリテラルがあります(3)。問合せのパフォーマンスが向上するように、これらの問合せオプションはいずれもデフォルトではオフになっています。

例1-24 SPARQL CONSTRUCT

例1-24に、foafボキャブラリを使用して従業員名のRDFグラフを構築するSPARQL CONSTRUCT問合せを示します。

SELECT subj$rdfterm, pred$rdfterm, obj$rdfterm
  FROM TABLE(SEM_MATCH(
    'PREFIX  ent: <http://www.example.org/enterprise/> 
     PREFIX foaf: <http://xmlns.com/foaf/0.1/>
     CONSTRUCT
      {?e foaf:givenName  ?fname .
       ?e foaf:familyName ?lname 
      }
     WHERE
      {?e ent:fname ?fname .
       ?e ent:lname ?lname 
      }',
    SEM_Models('enterprise'),
    SEM_Rulebases('RDFS'),
    null, null));

例1-25 解の修飾子を含むCONSTRUCT

SPARQLの解の修飾子をCONSTRUCT問合せで使用できます。例1-25に、ORDER BYとLIMITを使用して、最も給与が高い2人の従業員のグラフを構築する方法を示します。LIMIT 2句はCONSTRUCT問合せ全体ではなく問合せパターンに適用されることに注意してください。つまり、問合せパターンは2つの結果行を返しますが、CONSTRUCT問合せ全体は6個のRDFトリプル(?eにバインドされた従業員2人に3個ずつ)を返します。

SELECT subj$rdfterm, pred$rdfterm, obj$rdfterm
  FROM TABLE(SEM_MATCH(
    'PREFIX  ent: <http://www.example.org/enterprise/> 
     PREFIX foaf: <http://xmlns.com/foaf/0.1/>
     CONSTRUCT
      { ?e ent:fname       ?fname .
        ?e ent:lname       ?lname .
        ?e ent:dateOfBirth ?dob }
     WHERE
      { ?e ent:fname  ?fname .
        ?e ent:lname  ?lname .
        ?e ent:salary ?sal
      }
     ORDER BY DESC(?sal)
     LIMIT 2',
    SEM_Models('enterprise'),
    SEM_Rulebases('RDFS'),
    null, null));

例1-26 SPARQL 1.1機能とCONSTRUCT

SPARQL 1.1の機能は、CONSTRUCT問合せパターン内でサポートされます。例1-26に、CONSTRUCT問合せで使用されている副問合せとSELECT式を示します。

SELECT subj$rdfterm, pred$rdfterm, obj$rdfterm
  FROM TABLE(SEM_MATCH(
    'PREFIX  ent: <http://www.example.org/enterprise/> 
     PREFIX foaf: <http://xmlns.com/foaf/0.1/>
     CONSTRUCT
      { ?e foaf:name  ?name }
     WHERE
      { SELECT ?e (CONCAT(?fname," ",?lname) AS ?name)
        WHERE { ?e ent:fname ?fname .
                ?e ent:lname ?lname }
      }',
    SEM_Models('enterprise'),
    SEM_Rulebases('RDFS'),
    null, null));

例1-27 名前付きグラフを含むSPARQL CONSTRUCT

名前付きグラフ・データをSPARQL CONSTRUCT問合せで返すことはできません。W3C SPARQL仕様に従って、RDFクワッドではなくRDFトリプルのみが返されるためです。ただし、FROM、FROM NAMEDおよびGRAPHキーワードは、WHERE句に定義された問合せパターンと一致する場合に使用できます。

例1-27は、名前付きグラフent:g1ent:g2のUNIONのent:nameトリプル、名前付きグラフent:g3ent:dateOfBirthトリプル、および名前付きグラフent:g4ent:ssnトリプルを含むRDFグラフを作成します。

SELECT subj$rdfterm, pred$rdfterm, obj$rdfterm
  FROM TABLE(SEM_MATCH(
    'PREFIX  ent: <http://www.example.org/enterprise/> 
     PREFIX foaf: <http://xmlns.com/foaf/0.1/>
     CONSTRUCT
      { ?e ent:name ?name .
        ?e ent:dateOfBirth ?dob .
        ?e ent:ssn ?ssn
      }
     FROM ent:g1
     FROM ent:g2
     FROM NAMED ent:g3
     FROM NAMED ent:g4
     WHERE
      { ?e foaf:name ?name .
        GRAPH ent:g3 { ?e ent:dateOfBirth ?dob }
        GRAPH ent:g4 { ?e ent:ssn ?ssn } 
      }',
    SEM_Models('enterprise'),
    SEM_Rulebases('RDFS'),
    null, null));

例1-28 SPARQL CONSTRUCTの標準形

SELECT subj$rdfterm, pred$rdfterm, obj$rdfterm
  FROM TABLE(SEM_MATCH(
    'PREFIX  ent: <http://www.example.org/enterprise/> 
     PREFIX foaf: <http://xmlns.com/foaf/0.1/>
     CONSTRUCT
      {?e foaf:givenName  ?fname .
       ?e foaf:familyName ?lname 
      }
     WHERE
      {?e ent:fname ?fname .
       ?e ent:lname ?lname 
      }',
    SEM_Models('enterprise'),
    SEM_Rulebases('RDFS'),
    null, null));

例1-29 SPARQL CONSTRUCTの短縮形

CONSTRUCTテンプレートがWHERE句とまったく同じ場合、CONSTRUCTの短縮形を使用できます。このケースではキーワードCONSTRUCTのみが必要です。WHERE句のグラフ・パターンもCONSTRUCTテンプレートとして使用されます。例1-29に、例1-28の短縮形を示します。

SELECT subj$rdfterm, pred$rdfterm, obj$rdfterm
  FROM TABLE(SEM_MATCH(
    'PREFIX  ent: <http://www.example.org/enterprise/> 
     PREFIX foaf: <http://xmlns.com/foaf/0.1/>
     CONSTRUCT
     WHERE
      {?e ent:fname ?fname .
       ?e ent:lname ?lname 
      }',
    SEM_Models('enterprise'),
    SEM_Rulebases('RDFS'),
    null, null));
1.6.4.1 SPARQL CONSTRUCTの一般的なワークフロー

SPARQL CONSTRUCTの一般的なワークフローでは、CONSTRUCT問合せを実行して、既存のセマンティク・モデルのRDFトリプル・データを抽出または変換し(あるいは両方を行い)、そのデータを既存または新規セマンティク・モデルにロードします。データのロードは、単純なINSERT文を使用するかSEM_APIS.BULK_LOAD_FROM_STAGING_TABLEプロシージャを実行して行います。

例1-30 SPARQL CONSTRUCTのワークフロー

例1-30は、既存のent:fnameおよびent:lnameトリプルからfoaf:nameトリプルを作成し、それらの新しいトリプルを元のモデルにバルク・ロードします。その後、元のモデルにfoaf:name値を問い合せることができます。

-- use create table as select to build a staging table 
CREATE TABLE STAB(RDF$STC_sub, RDF$STC_pred, RDF$STC_obj) AS
SELECT subj$rdfterm, pred$rdfterm, obj$rdfterm
FROM TABLE(SEM_MATCH(
 'PREFIX  ent: <http://www.example.org/enterprise/> 
  PREFIX foaf: <http://xmlns.com/foaf/0.1/>
  CONSTRUCT
   { ?e foaf:name  ?name }
  WHERE
   { SELECT ?e (CONCAT(?fname," ",?lname) AS ?name)
     WHERE { ?e ent:fname ?fname .
             ?e ent:lname ?lname }
   }',
 SEM_Models('enterprise'),
 null, null, null)); 
 
-- grant privileges on STAB
GRANT SELECT ON STAB TO MDSYS;
 
-- bulk load data back into the enterprise model
BEGIN
  SEM_APIS.BULK_LOAD_FROM_STAGING_TABLE(
    model_name=>'enterprise',
    table_owner=>'rdfuser',
    table_name=>'stab',
    flags=>' parallel_create_index parallel=4 ');
END;
/
 
-- query for foaf:name data
SELECT e$rdfterm, name$rdfterm
FROM TABLE(SEM_MATCH(
 'PREFIX foaf: <http://xmlns.com/foaf/0.1/>
  SELECT ?e ?name
  WHERE { ?e foaf:name ?name }',
 SEM_Models('enterprise'),
null, null, null));

SPARQL CONSTRUCT問合せの詳細は、W3C SPARQL仕様、特にhttp://www.w3.org/TR/sparql11-query/#constructも参照してください。

1.6.5 グラフ・パターン: SPARQL DESCRIBE構文のサポート

SEM_MATCHでは、問合せパラメータに完全指定のSPARQL DESCRIBE問合せを使用できます。

SPARQL DESCRIBE問合せは、RDFデータセットの調査に役立ちます。データセットで使用される正確なRDFプロパティの情報を把握していなくても、指定された1つのリソースまたは一連のリソースについて簡単に情報を見つけることができます。DESCRIBE問合せはリソースrの説明を返します。この説明は、主語または目的語の位置にrを含む、問合せデータセットの一連のRDFトリプルです。

CONSTRUCT問合せと同じく、DESCRIBE問合せは結果バインディングのかわりにRDFグラフを返します。したがって、各DESCRIBE問合せはCONSTRUCT問合せと同じ列を返します(戻り列のリストは、「グラフ・パターン: SPARQL CONSTRUCT構文のサポート」を参照してください)。

SPARQL DESCRIBE問合せはSPARQL SELECT問合せと同じ構文を使用しますが、最上位のSELECT句をDESCRIBE句で置き換えます。DESCRIBE句の構成として、DESCRIBEキーワードの後に一連のURIまたは変数(あるいは両方)を空白で区切って指定するか、DESCRIBEキーワードの後に* (1つのアスタリスク)を指定します。

SPARQL DESCRIBE問合せに影響を与えるSEM_MATCH問合せオプションが2つあります。CONSTRUCT_UNIQUE=TおよびCONSTRUCT_STRICT=Tです。CONSTRUCT_UNIQUE=Tによって結果から重複したトリプルが消去され、CONSTRUCT_STRICT=Tによって結果から無効なトリプルが消去されます。これらのオプションは両方ともデフォルトではオフになっています。これらのオプションの詳細は、「グラフ・パターン: SPARQL CONSTRUCT構文のサポート」を参照してください。

SPARQL DESCRIBET問合せの詳細は、W3C SPARQL仕様、特にhttp://www.w3.org/TR/sparql11-query/#describeも参照してください。

例1-31 SPARQL DESCRIBEの短縮形

SPARQL DESCRIBEの短縮形は、一定の1つのURIを記述するために用意されています。短縮形ではDESCRIBE句のみが必要です。例1-31に、SPARQL DESCRIBE問合せの短縮形を示します。

SELECT subj$rdfterm, pred$rdfterm, obj$rdfterm
FROM TABLE(SEM_MATCH(
 'DESCRIBE <http://www.example.org/enterprise/emp_1>',
 SEM_Models('enterprise'),
null, null, null));

例1-32 SPARQL DESCRIBEの標準形

SPARQL DESCRIBEの標準形では、DESCRIBE句とSPARQL問合せパターン(解の修飾子を含む場合もある)が指定されます。例1-32に、所属部門がニュー・ハンプシャーにあるすべての従業員を説明するSPARQL DESCRIBE問合せを示します。

SELECT subj$rdfterm, pred$rdfterm, obj$rdfterm
FROM TABLE(SEM_MATCH(
 'PREFIX  ent: <http://www.example.org/enterprise/>
  DESCRIBE ?e
  WHERE 
   { ?e ent:department ?dept .
     ?dept ent:locatedIn "New Hampshire" }',
 SEM_Models('enterprise'),
null, null, null));

例1-33 DESCRIBE *

例1-32に示す標準形のDESCRIBEでは、DESCRIBE句に指定された変数にバインドされるすべてのリソースが説明されます。例1-32では、問合せパターンから返され、?eにバインドされているすべての従業員が説明されます。DESCRIBE *が使用されると、問合せに含まれるすべての変数が説明されます。

例1-33例1-32を変更したもので、従業員(?eにバインド)と部門(?deptにバインド)の両方を説明しています。

SELECT subj$rdfterm, pred$rdfterm, obj$rdfterm
FROM TABLE(SEM_MATCH(
 'PREFIX  ent: <http://www.example.org/enterprise/>
  DESCRIBE *
  WHERE 
   { ?e ent:department ?dept .
     ?dept ent:locatedIn "New Hampshire" }',
 SEM_Models('enterprise'),
null, null, null));

1.6.6 グラフ・パターン: SPARQL SELECT構文のサポート

中カッコのグラフ・パターンに加えて、SEM_MATCHでは、queryパラメータに完全指定のSPARQL SELECT問合せを使用できます。SPARQL SELECT構文オプションを使用すると、SEM_MATCHは問合せ構成要素のBASE、PREFIX、SELECT、SELECT DISTINCT、FROM、FROM NAMED、WHERE、ORDER BY、LIMITおよびOFFSETをサポートします。各SPARQL SELECT構文の問合せは、SELECT句とグラフ・パターンを含める必要があります。

SEM_MATCHを使用する場合の中カッコとSPARQL SELECT構文の主な違いは、SPARQL SELECT構文を使用する場合、SPARQL SELECT句に出現している変数のみがSEM_MATCHから戻されるところにあります。

SPARQL SELECT構文を使用する場合、SEM$ROWNUMという1つの追加列がSEM_MATCHから戻されます。このNUMBER列を使用して、結果の順序がSPARQL ORDER BY句で指定された順序と一致するようにSEM_MATCH問合せの結果を並べ替えることができます。

SPARQL ORDER BY句を使用すると、SEM_MATCH問合せの結果を並べ替えることができます。この句によって、指定された問合せの結果を並べ替えるために使用する一連のコンパレータを指定します。コンパレータは、変数、RDF語句、算術演算子(+、-、*、/)、ブール演算子と論理連結語(||、&&、!)、比較演算子(<、>、<=、>=、=、!=)およびFILTER式で使用可能な任意の関数で作成される式で構成されます。

SPARQL SELECT問合せを評価する場合は、次の順序で操作を実行します。

  1. グラフ・パターン照合

  2. グループ化(「グループ化と集計」を参照してください。)

  3. 集計(「グループ化と集計」を参照してください。)

  4. HAVING (「グループ化と集計」を参照してください。)

  5. VALUES (「値の割当て」を参照してください。)

  6. SELECT式

  7. ORDER BY

  8. 射影

  9. DISTINCT

  10. OFFSET

  11. LIMIT

SPARQL BASE、PREFIX、SELECT、SELECT DISTINCT、FROM、FROM NAMED、WHERE、ORDER BY、LIMITおよびOFFSET構成要素については、W3C SPARQL仕様、特にhttp://www.w3.org/TR/sparql11-query/を参照してください。

例1-34 SPARQL PREFIX、SELECTおよびWHERE句

例1-34では、次のSPARQL構成要素を使用しています。

  • SPARQL PREFIX句(http://www.example.org/family/およびhttp://xmlns.com/foaf/0.1/名前空間に対して略称を指定する場合)

  • SPARQL SELECT句: 問合せから抽出する変数のセットを指定します。

  • SPARQL WHERE句: 問合せグラフ・パターンを指定します。

SELECT y, name
  FROM TABLE(SEM_MATCH(
    'PREFIX : <http://www.example.org/family/> 
     PREFIX foaf: <http://xmlns.com/foaf/0.1/>
     SELECT ?y ?name
     WHERE
     {?x :grandParentOf ?y . 
      ?x foaf:name ?name }',
    SEM_Models('family'),
    SEM_Rulebases('RDFS','family_rb'), 
    null, null));

例1-34では、y、y$RDFVID、y$_PREFIX、y$_SUFFIX、y$RDFVTYP、y$RDFCLOB、y$RDFLTYP、y$RDFLANG、name、name$RDFVID、name$_PREFIX、name$_SUFFIX、name$RDFVTYP、name$RDFCLOB、name$RDFLTYP、name$RDFLANGおよびSEM$ROWNUMの各列を戻します。

例1-35 SPARQL SELECT * (トリプル・パターン内のすべての変数)

SPARQL SELECT句では、(A)一連の変数または式あるいはその両方(「SELECT句の式」を参照)を指定するか、(B) アスタリスク(*)を使用して、指定されたトリプル・パターンで出現するすべての変数を射影します。例1-35では、SPARQL SELECT句を使用して、指定されたトリプル・パターンで出現するすべての変数を選択しています。

SELECT x, y, name
  FROM TABLE(SEM_MATCH(
    'PREFIX : <http://www.example.org/family/> 
     PREFIX foaf: <http://xmlns.com/foaf/0.1/>
     SELECT *
     WHERE
     {?x :grandParentOf ?y . 
      ?x foaf:name ?name }',
    SEM_Models('family'),
    SEM_Rulebases('RDFS','family_rb'), 
    null, null));

例1-36 SPARQL SELECT DISTINCT

DISTINCTキーワードをSELECTの後に使用すると重複結果行を除外できます。例1-36では、SELECT DISTINCTを使用して重複しない名前のみを選択しています。

SELECT name
  FROM TABLE(SEM_MATCH(
    'PREFIX : <http://www.example.org/family/> 
     PREFIX foaf: <http://xmlns.com/foaf/0.1/>
     SELECT DISTINCT ?name
     WHERE
     {?x :grandParentOf ?y . 
      ?x foaf:name ?name }',
    SEM_Models('family'),
    SEM_Rulebases('RDFS','family_rb'), 
    null, null));

例1-37 FROMおよびFROM NAMEDを使用したRDFデータセットの指定

SPARQL FROMおよびFROM NAMEDは、問合せに対してRDFデータセット指定する場合に使用します。FROM句はデフォルト・グラフを構成するグラフのセットを指定する場合に使用し、FROM NAMED句は名前付きグラフ・セットを構成するグラフ・セットを指定する場合に使用します。例1-37では、FROMおよびFROM NAMEDを使用して、<http://www.friends.com/friends>および<http://www.contacts.com/contacts>グラフの和集合から電子メール・アドレスと友人を選択し、<http://www.example.org/family/Smith>および<http://www.example.org/family/Jones>グラフから祖父母情報を選択しています。

SELECT x, y, z, email
  FROM TABLE(SEM_MATCH(
    'PREFIX : <http://www.example.org/family/> 
     PREFIX foaf: <http://xmlns.com/foaf/0.1/>
     PREFIX friends: <http://www.friends.com/>
     PREFIX contacts: <http://www.contacts.com/>
     SELECT *
     FROM friends:friends
     FROM contacts:contacts
     FROM NAMED :Smith
     FROM NAMED :Jones
     WHERE
     {?x foaf:frendOf ?y .
      ?x :email ?email .
      GRAPH ?g {
        ?x :grandParentOf ?z }
     }',
    SEM_Models('family'),
    SEM_Rulebases('RDFS','family_rb'), 
    null, null));

例1-38 SPARQL ORDER BY

SPARQL ORDER BY句の場合:

  • 単一の変数の順序付け条件には前後のカッコは不要ですが、より複雑な順序付け条件にはカッコが必要です。

  • オプションのASC()またはDESC()順序修飾子を使用して、それぞれ昇順または降順となる目的の順序を指定できます。デフォルトの順序は昇順です。

  • SEM_MATCHでSPARQL ORDER BYを使用する場合、取り囲んでいるSQLブロック全体を通じて目的の順序を維持するためには、格納側のSQL問合せをSEM$ROWNUMで並べ替える必要があります。

例1-38では、SPARQL ORDER BY句ですべてのカメラを選択し、タイプの降順かつ合計(price * (1 - discount) * (1 + tax))の昇順になるように順序を指定しています。

SELECT *
  FROM TABLE(SEM_MATCH(
    'PREFIX : <http://www.example.org/electronics/> 
     SELECT * 
     WHERE
      {?x :price ?p .
       ?x :discount ?d .
       ?x :tax ?t .
       ?x :cameraType ?cType .
      }
     ORDER BY DESC(?cType) ASC(?p * (1-?d) * (1+?t))',
    SEM_Models('electronics'),
    SEM_Rulebases('RDFS'), 
    null, null))
ORDER BY SEM$ROWNUM;

例1-39 SPARQL LIMIT

SPARQL LIMITおよびSPARQL OFFSETは、問合せの解の異なるサブセットを選択するために使用できます。例1-39ではSPARQL LIMITを使用して最も安価なカメラを5つ選択し、例1-40ではSPARQL LIMITおよびOFFSETを使用して5番目から10番目に安価なカメラを選択しています。

SELECT *
  FROM TABLE(SEM_MATCH(
    'PREFIX : <http://www.example.org/electronics/> 
     SELECT ?x ?cType ?p
     WHERE
      {?x :price ?p .
       ?x :cameraType ?cType .
      }
     ORDER BY ASC(?p)
     LIMIT 5',
    SEM_Models('electronics'),
    SEM_Rulebases('RDFS'), 
    null, null))
ORDER BY SEM$ROWNUM;

例1-40 SPARQL OFFSET

SELECT *
  FROM TABLE(SEM_MATCH(
    'PREFIX : <http://www.example.org/electronics/> 
     SELECT ?x ?cType ?p
     WHERE
      {?x :price ?p .
       ?x :cameraType ?cType .
      }
     ORDER BY ASC(?p)
     LIMIT 5
     OFFSET 5',
    SEM_Models('electronics'),
    SEM_Rulebases('RDFS'), 
    null, null))
ORDER BY SEM$ROWNUM;

例1-41 完全なURIを使用した問合せ

SPARQL BASEキーワードは、グローバル接頭辞を設定するために使用します。すべての相対IRIは、「Uniform Resource Identifier (URI): Generic Syntax」(RFC3986)(http://www.ietf.org/rfc/rfc3986.txt)の5.2項で説明されている基本的なアルゴリズムを使用して、ベースIRIで解決されます。例1-41は完全なURIを使用する簡単な問合せで、例1-42はベースIRIを使用する同等の問合せです。

SELECT *
  FROM TABLE(SEM_MATCH(
    'SELECT ?employee ?position
     WHERE
      {?x <http://www.example.org/employee> ?p .
       ?p <http://www.example.org/employee/name> ?employee .
       ?p <http://www.example.org/employee/position> ?pos .
       ?pos <http://www.example.org/positions/name> ?position
      }',
    SEM_Models('enterprise'),
    null, 
    null, null))
ORDER BY 1,2;

例1-42 ベースIRIを使用した問合せ

SELECT *
  FROM TABLE(SEM_MATCH(
    'BASE <http://www.example.org/>
     SELECT ?employee ?position
     WHERE
      {?x <employee> ?p .
       ?p <employee/name> ?employee .
       ?p <employee/position> ?pos .
       ?pos <positions/name> ?position
      }',
    SEM_Models('enterprise'),
    null, 
    null, null))
ORDER BY 1,2;

1.6.7 グラフ・パターン: SPARQL 1.1の構成要素のサポート

SEM_MATCHでは、次のSPARQL 1.1の構成要素がサポートされています。

1.6.7.1 SELECT句の式

SELECT句では式を使用して、問合せから式の値を射影することができます。SELECT式は、変数、RDF語句、算術演算子(+、-、*、/)、ブール演算子と論理連結語(||、&&、!)、比較演算子(<、>、<=、>=、=、!=)およびFILTER式で使用可能な任意の関数で構成されます。式は、ASキーワードを使用して別名として単一の変数を指定する必要があり、<expression> AS <alias>フラグメント全体をカッコで囲む必要があります。この別名変数は、問合せで事前に定義することはできません。SELECT式は、前のSELECT式(つまり、SELECT句の前の方で指定された式)の結果を参照する場合があります。

例1-43 SPARQL SELECT式

例1-43では、SELECT式を使用してカメラごとの合計を射影しています。

SELECT *
  FROM TABLE(SEM_MATCH(
    'PREFIX : <http://www.example.org/electronics/> 
     SELECT ?x ((?p * (1-?d) * (1+?t)) AS ?totalPrice) 
     WHERE
      {?x :price ?p .
       ?x :discount ?d .
       ?x :tax ?t .
       ?x :cameraType ?cType .
      }',
    SEM_Models('electronics'),
    SEM_Rulebases('RDFS'), 
    null, null));

例1-44 SPARQL SELECT式(2)

例1-44では、2つのSELECT式を使用して、売上税がある場合とない場合の割引価格を射影しています。

SELECT *
  FROM TABLE(SEM_MATCH(
    'PREFIX : <http://www.example.org/electronics/> 
     SELECT ?x ((?p * (1-?d)) AS ?preTaxPrice) ((?preTaxPrice * (1+?t)) AS ?finalPrice)
     WHERE
      {?x :price ?p .
       ?x :discount ?d .
       ?x :tax ?t .
       ?x :cameraType ?cType .
      }',
    SEM_Models('electronics'),
    SEM_Rulebases('RDFS'), 
    null, null));
1.6.7.2 副問合せ

副問合せは、SPARQL SELECT構文で可能です。つまり、完全指定のSPARQL SELECT問合せが、他のSPARQL SELECT問合せ内に埋め込まれる場合があります。副問合せには、問合せのサブコンポーネントからの結果数を制限する場合など、多くの用途があります。

例1-45 SPARQL SELECT副問合せ

例1-45では、最も安価なカメラを製造するメーカーを検索し、このメーカーが製造した他のすべてのカメラを検索するために副問合せを使用しています。

SELECT *
  FROM TABLE(SEM_MATCH(
    'PREFIX : <http://www.example.org/electronics/> 
     SELECT ?c1
     WHERE {?c1 rdf:type :Camera .
            ?c1 :manufacturer ?m .
            {
             SELECT ?m
             WHERE {?c2 rdf:Type :Camera .
                    ?c2 :price ?p .
                    ?c2 :manufacturer ?m .
             }
             ORDER BY ASC(?p)
             LIMIT 1
            }
     }',
    SEM_Models('electronics'),
    SEM_Rulebases('RDFS'), 
    null, null));

副問合せが最初に論理的に評価され、その結果が外部問合せに射影されます。外部問合せから参照できるのは、副問合せのSELECT句で射影された変数のみです。

1.6.7.3 グループ化と集計

グループ化を実行するにはGROUP BYキーワードを使用します。構文上、GROUP BYキーワードはWHERE句の後、および解の修飾子(ORDER BYまたはLIMITなど)の前に使用する必要があります。

集計は、グループ内の結果全体の値を計算するために使用されます。集計は値のコレクションを操作して、結果として単一の値を生成します。SEM_MATCHは、組込みの集計としてCOUNT、SUM、MIN、MAX、AVG、GROUP_CONCATおよびSAMPLEをサポートしています。これらの集計を、表1-15で説明します。

表1-15 組込みの集計

集計 説明

AVG(expression)

グループ内の値に対するexpressionの平均値を返します。

COUNT(* | expression)

expressionがグループ内にバインドされた非エラー値を持つ回数がカウントされ、アスタリスク(*)ではグループ内の結果数がカウントされます。

GROUP_CONCAT(expression [; SEPARATOR = "STRING"])

グループ内の値に関して、expressionの文字列連結を実行します。オプションのセパレータ文字列を指定すると、各値の間にセパレータ文字が配置されます。

MAX(expression)

SPARQL ORDER BYによって定義される順序付けに基づいて、グループ内のexpressionの最大値を戻します。

MIN(expression)

SPARQL ORDER BYによって定義される順序付けに基づいて、グループ内のexpressionの最少値を戻します。

SAMPLE(expression)

グループから単一の任意の値と評価されるexpressionを戻します。

SUM(expression)

グループ内の値に関してexpressionの数値合計を計算します。

グループ化と集計の使用時には、変数参照に特定の制限が適用されます。グループ化変数(GROUP BY句の単一の変数)およびGROUP BY値割当てからの別名変数のみを、SELECT句またはHAVING句内の非集計式で使用できます。

例1-46 簡単なグループ化の問合せ

例1-46に、GROUP BYキーワードを使用してすべての種類のカメラを検索する問合せを示します。

SELECT *
  FROM TABLE(SEM_MATCH(
    'PREFIX : <http://www.example.org/electronics/> 
     SELECT ?cType
     WHERE
      {?x rdf:type :Camera .
       ?x :cameraType ?cType .
      }
     GROUP BY ?cType',
    SEM_Models('electronics'),
    SEM_Rulebases('RDFS'), 
    null, null));

グループ化問合せは、グループ化式(例1-46?cType)に基づいて問合せ結果をグループのコレクションに分割して、グループ内の各結果がグループ化式に関しては同じ値を持つようにします。グループ操作の最終結果には、各グループに1つの行が含まれます。

例1-47 複雑なグループ化式

グループ化式では、変数、式、または「<expression> as <alias>」の形式を持つ値割当てを1つ以上、ひと続きで指定します。例1-47は、グループ化式で各タイプのコンポーネントを1つずつ使用しているグループ化問合せを示しています。

SELECT *
  FROM TABLE(SEM_MATCH(
    'PREFIX : <http://www.example.org/electronics/> 
     SELECT ?cType ?totalPrice
     WHERE
      {?x rdf:type :Camera .
       ?x :cameraType ?cType .
       ?x :manufacturer ?m .
       ?x :price ?p .
       ?x :tax ?t .
      }
     GROUP BY ?cType (STR(?m)) ((?p*(1+?t)) AS ?totalPrice)',
    SEM_Models('electronics'),
    SEM_Rulebases('RDFS'),
    null, null));

例1-48 集計

例1-48では、集計を使用して、各種類のカメラの最高、最低、平均価格を選択しています。

SELECT *
  FROM TABLE(SEM_MATCH(
    'PREFIX : <http://www.example.org/electronics/> 
     SELECT ?cType 
            (MAX(?p) AS ?maxPrice) 
            (MIN(?p) AS ?minPrice) 
            (AVG(?p) AS ?avgPrice)
     WHERE
      {?x rdf:type :Camera .
       ?x :cameraType ?cType .
       ?x :manufacturer ?m .
       ?x :price ?p .
      }
     GROUP BY ?cType',
    SEM_Models('electronics'),
    SEM_Rulebases('RDFS'),
    null, null));

例1-49 グループ化なしの集計

集計をグループ化式なしで使用すると、結果セット全体が単一のグループとして処理されます。例1-49では、データセット全体のカメラの合計数を計算しています。

SELECT *
  FROM TABLE(SEM_MATCH(
    'PREFIX : <http://www.example.org/electronics/> 
     SELECT (COUNT(?x) as ?cameraCnt)
     WHERE
      { ?x rdf:type :Camera 
      }',
    SEM_Models('electronics'),
    SEM_Rulebases('RDFS'),
    null, null));

例1-50 DISTINCTを使用した集計

DISTINCTキーワードは、必要に応じて、集計ごとに修飾子として使用できます。DISTINCTを使用すると、集計を計算する前に各グループから重複値が除外されます。構文上、DISTINCTは集計の最初の引数として使用される必要があります。例1-50では、重複なしのカメラ・メーカー数を検索するためにDISTINCTを使用しています。この場合、STR(?m)の重複値は、カウント前に除外されます。

SELECT *
  FROM TABLE(SEM_MATCH(
    'PREFIX : <http://www.example.org/electronics/> 
     SELECT (COUNT(DISTINCT STR(?m)) as ?mCnt)
     WHERE
      { ?x rdf:type :Camera .
        ?x :manufacturer ?m
      }',
    SEM_Models('electronics'),
    SEM_Rulebases('RDFS'),
    null, null));

例1-51 HAVING句

制約に基づいてグループをフィルタ処理するには、HAVINGキーワードを使用できます。HAVING式は、変数、RDF語句、算術演算子(+、-、*、/)、ブール演算子と論理連結語(||、&&、!)、比較演算子(<、>、<=、>=、=、!=)、集計、およびFILTER式で使用可能な任意の関数で構成できます。構文上、HAVINGキーワードはGROUP BY句の後、および他の解の修飾子(ORDER BYまたはLIMITなど)の前に使用します。

例1-51では、HAVING式を使用して、200ドル未満のカメラを販売するすべてのメーカーを検索しています。

SELECT *
  FROM TABLE(SEM_MATCH(
    'PREFIX : <http://www.example.org/electronics/> 
     SELECT ?m
     WHERE
      { ?x rdf:type :Camera .
        ?x :manufacturer ?m .
        ?x :price ?p
      }
     GROUP BY ?m
     HAVING (MIN(?p) < 200)
     ORDER BY ASC(?m)',
    SEM_Models('electronics'),
    SEM_Rulebases('RDFS'),
    null, null));
1.6.7.4 否定

SEM_MATCHでは、SPARQL問合せパターンでNOT EXISTSおよびMINUSの2つの形式の否定がサポートされています。NOT EXISTSはグラフ・パターンが一致したかどうかに基づいて結果をフィルタ処理するために使用可能で、MINUSは別のグラフ・パターンとの関係に基づいて解を除外するために使用できます。

例1-52 NOT EXISTSによる否定

例1-52では、NOT EXISTS FILTERを使用して、ユーザー・レビューのないカメラを選択しています。

SELECT *
  FROM TABLE(SEM_MATCH(
    'PREFIX : <http://www.example.org/electronics/> 
     SELECT ?x ?cType ?p
     WHERE
      {?x :price ?p .
       ?x :cameraType ?cType .
       FILTER( NOT EXISTS({?x :userReview ?r}) )
      }',
    SEM_Models('electronics'),
    SEM_Rulebases('RDFS'), 
    null, null));

例1-53 EXISTS

逆に、EXISTS演算子は、パターンの一致を確認する場合に使用できます。例1-53では、EXISTS FILTERを使用して、ユーザー・レビューを持つカメラのみを選択しています。

SELECT *
  FROM TABLE(SEM_MATCH(
    'PREFIX : <http://www.example.org/electronics/> 
     SELECT ?x ?cType ?p
     WHERE
      {?x :price ?p .
       ?x :cameraType ?cType .
       FILTER( EXISTS({?x :userReview ?r}) )
      }',
    SEM_Models('electronics'),
    SEM_Rulebases('RDFS'), 
    null, null));

例1-54 MINUSによる否定

例1-54では、MINUSを使用して、例1-52と同じ結果を得ています。MINUSパターンの解と互換性がない解のみが、結果に含まれます。つまり、解がすべての共有変数にMINUSパターンの解と同じ値を持つ場合、それは結果から除外されます。

SELECT *
  FROM TABLE(SEM_MATCH(
    'PREFIX : <http://www.example.org/electronics/> 
     SELECT ?x ?cType ?p
     WHERE
      {?x :price ?p .
       ?x :cameraType ?cType .
       MINUS {?x :userReview ?r}
      }',
    SEM_Models('electronics'),
    SEM_Rulebases('RDFS'), 
    null, null));

例1-55 NOT EXISTSによる否定(2)

NOT EXISTSとMINUSは2つの異なるスタイルの否定を表し、特定の状況では異なる結果を持ちます。例としては、否定パターンと残りの問合せの間で変数が共有されない場合が挙げられます。たとえば、例1-55のNOT EXISTS問合せでは{?subj ?prop ?obj}がどのトリプルにも一致するためすべての解が除外されますが、例1-56のMINUS問合せでは、共有変数がないため除外される解はありません。

SELECT *
  FROM TABLE(SEM_MATCH(
    'PREFIX : <http://www.example.org/electronics/> 
     SELECT ?x ?cType ?p
     WHERE
      {?x :price ?p .
       ?x :cameraType ?cType .
       FILTER( NOT EXISTS({?subj ?prop ?obj}) )
      }',
    SEM_Models('electronics'),
    SEM_Rulebases('RDFS'),
    null, null));

例1-56 MINUSによる否定(2)

SELECT *
  FROM TABLE(SEM_MATCH(
    'PREFIX : <http://www.example.org/electronics/> 
     SELECT ?x ?cType ?p
     WHERE
      {?x :price ?p .
       ?x :cameraType ?cType .
       MINUS {?subj ?prop ?obj}
      }',
    SEM_Models('electronics'),
    SEM_Rulebases('RDFS'),
    null, null));
1.6.7.5 値の割当て

SEM_MATCHには、値をSPARQL問合せの変数に割り当てる様々な方法が提供されています。

式の値を新しい変数に割り当てる方法には、(1)SELECT句の式、(2)GROUP BY句の式、および(3)BINDキーワードの3つがあります。どの場合も、新しい変数を問合せで事前に定義しておく必要はありません。割当て後は、この新しい変数を問合せで使用して、結果に戻すことが可能です。「SELECT句の式」で説明したように、値割当ての構文は(<expression> AS <alias>)となり、aliasは新しい変数を示し、たとえば((?price * (1+?tax)) AS ?totalPrice)とします。

例1-57 ネストしたSELECT式

例1-57では、ネストしたSELECT式を使用して、カメラの合計価格を計算し、その値を変数(?totalPrice)に割り当てています。その後、この変数を外部問合せのFILTERで使用して、200ドル未満のカメラを検索します。

SELECT *
 FROM TABLE(SEM_MATCH(
   'PREFIX : <http://www.example.org/electronics/> 
    SELECT ?x ?cType ?totalPrice
    WHERE
     {?x :cameraType ?cType .
       { SELECT ?x ( ((?price*(1+?tax)) AS ?totalPrice )
         WHERE { ?x :price ?price .
                 ?x :tax ?tax }
       }
      FILTER (?totalPrice < 200)
     }',
   SEM_Models('electronics'),
   SEM_Rulebases('RDFS'),
   null, null));

例1-58 BIND

BINDキーワードは、基本グラフ・パターン内で値を割り当てるために使用可能で、構文上は同等のネストしたSELECT式より簡潔です。例1-58では、BINDキーワードを使用して、例1-57と論理的に同等な問合せを表しています。

SELECT *
  FROM TABLE(SEM_MATCH(
    'PREFIX : <http://www.example.org/electronics/> 
     SELECT ?x ?cType ?totalPrice
     WHERE
      {?x :cameraType ?cType .
       ?x :price ?price .
       ?x :tax ?tax .
       BIND ( ((?price*(1+?tax)) AS ?totalPrice )
       FILTER (?totalPrice < 200)
      }',
    SEM_Models('electronics'),
    SEM_Rulebases('RDFS'),
    null, null));

例1-59 GROUP BY式

GROUP BY句の値割当ては、その後SELECT句、HAVING句および外部問合せ(ネストしたグループ化問合せの場合)で使用することができます。例1-59では、GROUP BY式を使用して、1000ドル未満の各価格のカメラの最大メガピクセル数を検索しています。

SELECT *
  FROM TABLE(SEM_MATCH(
    'PREFIX : <http://www.example.org/electronics/> 
     SELECT ?totalPrice (MAX(?mp) as ?maxMP)
     WHERE
      {?x rdf:type :Camera .
       ?x :price ?price .
       ?x :tax ?tax .
       GROUP BY ( ((?price*(1+?tax)) AS ?totalPrice )
       HAVING (?totalPrice < 1000)
      }',
    SEM_Models('electronics'),
    SEM_Rulebases('RDFS'),
    null, null));

例1-60 VALUES

新しい変数に式の値を割り当てる方法には、前述の3つの方法の他にVALUESキーワードを使用する方法があり、順序付けられていない解の順序を取得して、結合操作によって問合せ結果と組み合せることができます。VALUESブロックは、問合せパターン内、またはSPARQL SELECT問合せブロックの末尾の解の修飾子の後に使用できます。VALUES構成要素は、副問合せで使用できます。

例1-60では、VALUESキーワードを使用して、問合せ結果を:Company1製造のDSLRカメラ、または:Company2製造の任意の種類のカメラに制限しています。キーワードUNDEFは、解の順序内でバインドされていない変数を表すために使用されます。

SELECT *
  FROM TABLE(SEM_MATCH(
    'PREFIX : <http://www.example.org/electronics/> 
     SELECT ?x ?cType ?m
     WHERE 
      { ?x rdf:type :Camera .
        ?x :cameraType ?cType .
        ?x :manufacturer ?m
      }
     VALUES (?cType ?m)
     { ("DSLR" :Company1)
       (UNDEF  :Company2) 
     }',
    SEM_Models('electronics'),
    SEM_Rulebases('RDFS'),
    null, null));

例1-61 簡略化されたVALUES構文

変数が1つの一般的な例では、簡略化された構文を使用できます。特に、変数および各解の前後のカッコは省略できます。例1-61は、簡略化された構文を使用して、問合せ結果を:Company1または:Company2によって製造されたカメラに制限しています。

SELECT *
  FROM TABLE(SEM_MATCH(
    'PREFIX : <http://www.example.org/electronics/> 
     SELECT ?x ?cType ?m
     WHERE 
      { ?x rdf:type :Camera .
        ?x :cameraType ?cType .
        ?x :manufacturer ?m
      }
     VALUES ?m
     { :Company1
       :Company2 
     }',
    SEM_Models('electronics'),
    SEM_Rulebases('RDFS'),
    null, null));

例1-62 インラインVALUESブロック

例1-62でも、問合せ結果を:Company1または:Company2製造のカメラに制限していますが、問合せパターン内でVALUESブロックを指定しています。

SELECT *
  FROM TABLE(SEM_MATCH(
    'PREFIX : <http://www.example.org/electronics/> 
     SELECT ?x ?cType ?m
     WHERE 
      { VALUES ?m { :Company1 :Company2 }
        ?x rdf:type :Camera .
        ?x :cameraType ?cType .
        ?x :manufacturer ?m
      }',
    SEM_Models('electronics'),
    SEM_Rulebases('RDFS'),
    null, null));
1.6.7.6 プロパティ・パス

SPARQLプロパティ・パスは、RDFグラフ内の2つのRDFリソース(ノード)の間の可能なパスを示しています。プロパティ・パスはトリプル・パターンの述語位置に出現するもので、トリプル・パターンの主語からトリプル・パターンの目的語までのパスを形成するプロパティ(エッジ)に制約を適用するために、正規表現のような構文を使用します。プロパティ・パスによって、SPARQL問合せはRDFグラフの任意の長さのパスを照合し、他のグラフ・パターンを表現する簡潔な方法を提供できます。

表1-16に、SPARQLプロパティ・パスの構築に使用可能な構文構成要素を示します。iriはIRIまたは接頭辞の付いた名前で、eltはプロパティ・パス要素で、それ自体が他のプロパティ・パス要素で構成される場合があります。

表1-16 プロパティ・パスの構文の構成要素

構文の構成要素 一致

iri

IRIまたは接頭辞の付いた名前。長さが1のパス。

^elt

逆のパス(目的語から主語へ)。

!iriまたは!(iri1 | … | irin)

否定プロパティ・セット。 iriiのいずれかではないIRI。

!^iriまたは!(iri1 | … | irij | ^irij+1 | … | ^irin)

逆のプロパティを持つ否定プロパティ・セット。iriiまたはirij+1...irinのいずれでもない逆パスのIRI。!^iri!(^iri)の短縮形。プロパティと逆のプロパティの順番は、どちらが先でも問題ありません。順不同で実行されます。

(elt)

グループ・パスelt(カッコは優先順位を制御します)。

elt1 / elt2

elt1elt2の順の順序パス。

elt1 | elt2

elt1またはelt2の代替パス(すべての可能性が試行されます)。

elt*

0個以上のeltのパス。

elt+

1個以上のeltのパス。

elt?

0個または1個のeltのパス。

構文構成要素の優先順位を、高いものから順に示します。

  • IRI、接頭辞の付いた名前

  • 否定プロパティ・セット

  • グループ

  • 単項演算子 *、?、+

  • 単項^逆リンク

  • バイナリ演算子 /

  • バイナリ演算子 |

グループ内の優先順位は左から右に評価されます。

プロパティ演算子+および*の特別な考慮事項

通常、+ (プラス記号)と* (アスタリスク)演算子を使用した、完全に無制限のグラフ・トラバースはコストが非常に高くなります。この理由から、デフォルトでは深度制限のある+演算子と*演算子が使用されます。デフォルトの深度制限は10です。また、深度制限の実装は並列で実行できます。ALL_MAX_PP_DEPTH(n) SEM_MATCH問合せオプションまたはMAX_PP_DEPTH(n)インラインHINT0問合せオプティマイザ・ヒントを使用して、深度制限設定を変更できます。完全に無制限のトラバースを実現するには、深度制限を1未満に設定して、CONNECT BYベースの実装に戻ります。

プロパティ・パスの問合せヒント

プロパティ・パス問合せのパフォーマンスに影響するその他の問合せヒントも使用できます。ALLOW_PP_DUP=T問合せオプションを*問合せや+問合せと使用すると、結果の重複を認めることができます。結果の重複が認められると、問合せから最初の行が早く戻されます。また、ALL_USE_PP_HASHおよびALL_USE_PP_NL問合せオプションは、プロパティ・パス表現を評価するときに使用される結合タイプに影響します。同様のUSE_PP_HASHおよびUSE_PP_NLインラインHINT0問合せオプティマイザ・ヒントも使用できます。

例1-63 SPARQLプロパティ・パス(rdfs:subClassOf関係を使用)

例1-63では、プロパティ・パスを使用して、rdfs:subClassOf関係の推移性に基づいてすべての男性を検索しています。プロパティ・パスでは、任意の数の連続的なrdfs:subClassOf関係の一致が可能です。

SELECT x, name
  FROM TABLE(SEM_MATCH(
    '{ ?x foaf:name ?name .
       ?x rdf:type ?t .
       ?t rdfs:subClassOf* :Male }',
    SEM_Models('family'),
    null, 
    SEM_ALIASES(SEM_ALIAS('','http://www.example.org/family/') 
                SEM_ALIAS('foaf',' http://xmlns.com/foaf/0.1/')),
    null));

例1-64 SPARQLプロパティ・パス(foaf:friendOfまたはfoaf:knows関係を使用)

例1-64では、プロパティ・パスを使用して、Scottの親しい友人(foaf:friendOfまたはfoaf:knows関係を使用して2ホップ以内に到達可能な人々)をすべて検索しています。

SELECT name
  FROM TABLE(SEM_MATCH(
    '{ { :Scott (foaf:friendOf | foaf:knows) ?f }
       UNION
       { :Scott (foaf:friendOf | foaf:knows)/(foaf:friendOf | foaf:knows) ?f }
       ?f foaf:name ?name .
       FILTER (!sameTerm(?f, :Scott)) }',
    SEM_Models('family'),
    null, 
    SEM_ALIASES(SEM_ALIAS('','http://www.example.org/family/'),
                SEM_ALIAS('foaf',' http://xmlns.com/foaf/0.1/')),
    null));

例1-65 プロパティ・パスの最大深度値の指定

例1-65では、ALL_MAX_PP_DEPTH(n)問合せオプション値を使用してすべてのプロパティ・パス表現に最大深度12を指定します。

SELECT x, name
  FROM TABLE(SEM_MATCH(
    '{ ?x foaf:name ?name .
       ?x rdf:type ?t .
       ?t rdfs:subClassOf* :Male }',
    SEM_Models('family'),
    null, 
    SEM_ALIASES(SEM_ALIAS('','http://www.example.org/family/') 
                SEM_ALIAS('foaf',' http://xmlns.com/foaf/0.1/')),
    null,
    null,
    ' ALL_MAX_PP_DEPTH(12) '));

例1-66 プロパティ・パス結合ヒントの指定

例1-66に、プロパティ・パス表現の評価にネステッド・ループ結合をリクエストするインラインHINT0問合せオプティマイザ・ヒントを示します。

SELECT x, name
  FROM TABLE(SEM_MATCH(
    '{ # HINT0={ USE_PP_NL }
       ?x foaf:name ?name .
       ?x rdf:type ?t .
       ?t rdfs:subClassOf* :Male }',
    SEM_Models('family'),
    null, 
    SEM_ALIASES(SEM_ALIAS('','http://www.example.org/family/') 
                SEM_ALIAS('foaf',' http://xmlns.com/foaf/0.1/')),
    null));

1.6.8 グラフ・パターン: SPARQL 1.1のフェデレーテッド問合せのサポート

SEM_MATCHは、SPARQL 1.1のフェデレーテッド問合せをサポートしています(http://www.w3.org/TR/sparql11-federated-query/#SPROTを参照)。SERVICE構成要素を使用して、指定したSPARQLエンドポイントURLから結果を取得できます。この機能により、ローカルのRDFデータ(ネイティブRDFデータまたはリレーショナル・データのRDFビュー)を、W3C標準準拠のSPARQLエンドポイントによって提供される他のRDFデータ(おそらくリモート)と組み合せることができます。

例1-67 すべてのトリプルを取得するSPARQL SERVICE句

例1-67は、SERVICE句を使用して、http://www.example1.org/sparqlにあるSPARQLエンドポイントからすべてのトリプルを取得する問合せです。

SELECT s, p, o
  FROM TABLE(SEM_MATCH(
    'SELECT ?s ?p ?o
     WHERE {
       SERVICE <http://www.example1.org/sparql>{ ?s ?p ?o }
     }',
    SEM_Models('electronics'),
    null, null, null, null, ' '));

例1-68 リモートとローカルのRDFデータを結合するSPARQL SERVICE句

例1-68は、リモートRDFデータとローカルRDFデータを結合します。この例は、ローカル・モデルelectronicsのカメラのタイプ?cTypeを、http://www.example1.org/sparqlのSPARQLエンドポイントのカメラの名前?nameに結合します。

SELECT cType, name
  FROM TABLE(SEM_MATCH(
    'PREFIX : <http://www.example.org/electronics/> 
     SELECT ?cType ?name
     WHERE {
       ?s :cameraType ?cType
       SERVICE <http://www.example1.org/sparql>{ ?s :name ?name }
      }',
    SEM_Models('electronics'),
    null, null, null, null, ' '));
1.6.8.1 フェデレーテッドSPARQL問合せの実行に必要な権限

SEM_MATCH問合せでSERVICE構成要素を使用するには、特定のデータベース権限が必要です。DBA権限を持つユーザーによって、SPARQL_SERVICE MDSYS関数のEXECUTE権限が付与される必要があります。次の例では、このアクセス権がRDFUSERという名前のユーザーに付与されます。

grant execute on mdsys.sparql_service to rdfuser;

また、アクセス制御リスト(ACL)を使用して、フェデレーテッド問合せを試行するユーザーにCONNECT権限を付与する必要があります。例1-69は、新しいACLを作成して、ユーザーRDFUSERにCONNECT権限を付与し、ドメイン*をACLに割り当てます。ACLの詳細は、『Oracle Database PL/SQLパッケージおよびタイプ・リファレンス』を参照してください。

例1-69 アクセス制御リストとホスト割当て

dbms_network_acl_admin.create_acl (
  acl       => 'rdfuser.xml',
  description => 'Allow rdfuser to query SPARQL endpoints',
  principal => 'RDFUSER',
  is_grant  => true,
  privilege => 'connect'
);
 
dbms_network_acl_admin.assign_acl (
  acl  => 'rdfuser.xml',
  host => '*'
);      

必要な権限が付与されると、SEM_MATCHからフェデレーテッド問合せを実行する準備が整います。

1.6.8.2 SPARQL SERVICEの結合プッシュ・ダウン

SPARQL SERVICEの結合プッシュ・ダウン(SERVICE_JPDWN=T)機能を使用すると、特定のSPARQL SERVICE問合せのパフォーマンスを改善できます。デフォルトでは、SERVICE句の問合せパターンがリモートSPARQLエンドポイントで最初に実行されます。このリモート実行のすべての結果が、問合せのローカルの部分に結合されます。この方法では、問合せのローカル部分の選択性が非常に高く、問合せのリモート部分の選択性が非常に低いと、パフォーマンスが低下することがあります。

SPARQL SERVICEの結合プッシュ・ダウン機能は、SERVICE句を複数含む問合せでは使用できません。

例1-70 SPARQL SERVICEの結合プッシュ・ダウン

例1-70に、SPARQL SERVICEの結合プッシュ・ダウン機能を示します。

SELECT s, prop, obj
  FROM TABLE(SEM_MATCH(
    'PREFIX : <http://www.example.org/electronics/> 
     SELECT ?s ?prop ?obj
     WHERE {
       ?s rdf:type   :Camera .
       ?s :modelName "Camera 12345"
       SERVICE <http://www.example1.org/sparql> { ?s ?prop ?obj }
      }',
    SEM_Models('electronics'),
    null, null, null, null, ' SERVICE_JPDWN=T '));

例1-70では、問合せのローカル部分ではごく少数の行が返されますが、問合せのリモート部分は完全に無制限であるためリモート・データセット全体が返されます。SERVICE_JPDWN=Tオプションが指定されると、SEM_MATCHはネステッド・ループ方式の評価を実行します。まず、問合せのローカル部分を実行してから、ローカル部分によって返された行ごとに、変更したリモート問合せを1回ずつ実行します。結合変数?sにかわって効率よく実行するFILTER句を使用してリモート問合せを変更します。たとえば、<urn:camera1><urn:camera2>?sのバインディングとして例1-70のローカル部分から返されると、2つの問合せ、{ ?s ?prop ?obj FILTER (?s = <urn:camera1>) }{ s ?prop ?obj FILTER (?s = <urn:camera2>) }がリモート・エンドポイントに送られます。

1.6.8.3 SPARQL SERVICE SILENT

SILENTキーワードがフェデレーテッド問合せで使用されるとき、指定されたリモートSPARQLエンドポイントにアクセスする際のエラーが無視されます。SERVICE SILENTリクエストが失敗すると、バインディングなしの1つの解が返されます。

例1-71は、OPTIONAL句内でSILENTキーワードと一緒にSERVICEを使用しています。このため、http://www.example1.org/sparqlにアクセスする際に接続エラーが発生しても、そのようなエラーは無視され、トリプル?s :cameratype ?kから取得されたすべての行が?nのnull値と結合されます。

例1-71 SILENTキーワードを含むSPARQL SERVICE

SELECT s, n
  FROM TABLE(SEM_MATCH(
    'PREFIX : <http://www.example.org/electronics/> 
     SELECT ?s ?n
     WHERE {
       ?s :cameraType ?k
       OPTIONAL { SERVICE SILENT <http://www.example1.org/sparql>{ ?k :name ?n } }
      }',
    SEM_Models('electronics'),
    null, null, null, null));
1.6.8.4 SPARQL SERVICEでのプロキシ・サーバーの使用

次の方法を使用して、SPARQL SERVICEリクエストをHTTPプロキシで送信できます。

  • 現在のセッションでリクエストに使用する必要があるHTTPプロキシを指定します。これは、UTL_HTTPパッケージのSET_PROXY関数を使用して行うことができます。例1-72は、HTTPリクエストで使用するプロキシproxy.example.comを設定し、ドメインexample2.comのホストに対するリクエストを除外します。(SET_PROXYプロシージャの詳細は、『Oracle Database PL/SQLパッケージおよびタイプ・リファレンス』を参照してください。)

  • SPARQL SERVICEリクエストのプロキシ・アドレスを設定できるようにするSERVICE_PROXY SEM_MATCHオプションを使用します。ただし、このケースでは例外を指定できません。すべてのリクエストは指定したプロキシ・サーバーに送信されます。例1-73に、ポート80のプロキシ・アドレスproxy.example.comが指定されたSEM_MATCH問合せを示します。

例1-72 UTL_HTTP.SET_PROXYでのプロキシ・サーバーの設定

BEGIN
  UTL_HTTP.SET_PROXY('proxy.example.com:80', 'example2.com');
END;
/

例1-73 SPARQL SERVICEでのプロキシ・サーバーの設定

SELECT *
  FROM TABLE(SEM_MATCH(
    'SELECT *
     WHERE {
       SERVICE <http://www.example1.org/sparql>{ ?s ?p ?o }
      }',
    SEM_Models('electronics'),
    null, null, null, null, ' SERVICE_PROXY=proxy.example.com:80 '));
1.6.8.5 HTTP基本認証でのSPARQLエンドポイントへのアクセス

HTTP基本認証でSPARQLエンドポイントへのアクセスを許可するには、ユーザー資格証明をセッション・コンテキストSDO_SEM_HTTP_CTXに保存する必要があります。DBA権限を持つユーザーが、基本認証の使用を希望するユーザーにこのコンテキストのEXECUTEを付与する必要があります。次の例では、このアクセス権をRDFUSERというユーザーに付与しています。

grant execute on mdsys.sdo_sem_http_ctx to rdfuser;

権限が付与されると、ユーザーは各SPARQLエンドポイントのユーザー名とパスワードをHTTP認証に保存する必要があります。これには、関数mdsys.sdo_sem_http_ctx.set_usrおよびmdsys.sdo_sem_http_ctx.set_pwdを使用します。次の例では、SPARQLエンドポイント(http://www.example1.org/sparql)のユーザー名とパスワードが設定されます。

BEGIN
  mdsys.sdo_sem_http_ctx.set_usr('http://www.example1.org/sparql','user');
  mdsys.sdo_sem_http_ctx.set_pwd('http://www.example1.org/sparql','pwrd');
END;
/

1.6.9 インライン問合せオプティマイザ・ヒント

SEM_MATCHでは、HINT0インライン問合せオプティマイザ・ヒントを許可するために、SPARQLコメント構成要素がオーバーロードされています。SPARQLのハッシュ(#)文字は、行のそれ以降の部分がコメントであることを示します。インライン・ヒントを特定のBGPと関連付けるには、HINT0ヒント文字列をSPARQLコメント内に配置し、開始中カッコ({)とBGPの最初のトリプル・パターンの間にコメントを挿入します。インライン・ヒントを使用すると、問合せ内の各BGPの実行計画に影響を与えることができます。

インライン・オプティマイザ・ヒントは、options引数を使用してSEM_MATCHに渡されるすべてのヒントをオーバーライドします。たとえば、インライン・オプティマイザ・ヒントを指定していない各BGPには、グローバルALL_ORDEREDヒントが適用されますが、インライン・ヒントを持つBGPには、ALL_ORDEREDヒントではなくインライン・ヒントが使用されます。

例1-74 インライン問合せオプティマイザ・ヒント (BGP_JOIN)

次の例は、インライン問合せオプティマイザ・ヒントを含む問合せです。

SELECT x, y, hp, cp
  FROM TABLE(SEM_MATCH(
    '{ # HINT0={ LEADING(t0) USE_NL(?x ?y ?bd) }
      ?x :grandParentOf ?y . ?x rdf:type :Male . ?x :birthDate ?bd
      OPTIONAL { # HINT0={ LEADING(t0 t1) BGP_JOIN(USE_HASH) }
                 ?x :homepage ?hp . ?x :cellPhoneNum ?cp }
     }',
    SEM_Models('family'),
    SEM_Rulebases('RDFS','family_rb'), 
    SEM_ALIASES(SEM_ALIAS('','http://www.example.org/family/')),
    null));

BGP_JOINヒントはBGP結合間に影響を与えるもので、BGP_JOIN(<join_type>)という構文を使用します(<join_type>はUSE_HASHまたはUSE_NLです)。例1-74では、BGP_JOIN(USE_HASH)ヒントを使用して、OPTIONAL BGPをその親BGPと結合する場合にハッシュ結合を使用する必要があることを指定しています。

インライン・オプティマイザ・ヒントは、options引数を使用してSEM_MATCHに渡されるすべてのヒントをオーバーライドします。たとえば、インライン・オプティマイザ・ヒントを指定していない各BGPには、グローバルALL_ORDEREDヒントが適用されますが、インライン・ヒントを持つBGPには、ALL_ORDEREDヒントではなくインライン・ヒントが使用されます。

例1-75 インライン問合せオプティマイザ・ヒント (ANTI_JOIN)

ANTI_JOINヒントは、NOT EXISTS句およびMINUS句の評価に影響を与えます。このヒントは、ANTI_JOIN(<join_type>)という構文で使用されます。ここで、<join_type>はHASH_AJ, NL_AJまたはMERGE_AJです。次の例では、ハッシュ非結合を使用するよう指定するヒントが使用されています。グローバルのALL_AJ_HASH、ALL_AJ_NL、ALL_AJ_MERGEをSEM_MATCHのオプション引数に使用して、問合せ全体で、すべてのNOT EXISTS句およびMINUS句に影響を与えることができます。

SELECT x, y
  FROM TABLE(SEM_MATCH(
    'SELECT ?x ?y
     WHERE {
       ?x :grandParentOf ?y . ?x rdf:type :Male . ?x :birthDate ?bd
       FILTER ( 
         NOT EXISTS {# HINT0={ ANTI_JOIN(HASH_AJ) }
                     ?x :homepage ?hp . ?x :cellPhoneNum ?cp })
     }',
    SEM_Models('family'),
    SEM_Rulebases('RDFS','family_rb'), 
    SEM_ALIASES(SEM_ALIAS('','http://www.example.org/family/')),
    null));

例1-76 インライン問合せオプティマイザ・ヒント(NON_NULL)

SPARQL SELECT句では、特定の変数が常にバインドされている(つまり結果の各行にはNULLでない値が含まれている)ことを示すHINT0={ NON_NULL}がサポートされています。このヒントにより、SELECTで生成された値に対する結合を問合せコンパイラで最適化できます。考えられるすべてのインプットに対して、式がNULLでない値を生成するとは限らないため、こうした最適化をデフォルトで適用することはできません。SELECT式でNULL値が生成されないことがわかっている場合には、NON_NULLヒントを使用することで、パフォーマンスが著しく向上します。このヒントは、SELECT式の「AS」キーワードの前に行のコメントで指定します。

次の例では、NON_NULLヒント・オプションがSEM_MATCH問合せで使用されており、?full_nameが必ずバインドされていることが明示されています。

SELECT s, t
  FROM TABLE(SEM_MATCH(
    'SELECT * WHERE {
       ?s :name ?full_name
       { SELECT (CONCAT(?fname, " ", ?lname) # HINT0={ NON_NULL }
                 AS ?full_name)
         WHERE { 
           ?t :fname ?fname .
           ?t :lname ?lname } 
         } 
     }',
    SEM_Models('family'),
    SEM_Rulebases('RDFS','family_rb'), 
    SEM_ALIASES(SEM_ALIAS('','http://www.example.org/family/')),
          null));

1.6.10 全文検索

Oracle固有のorardf:textContains SPARQL FILTER関数は、MDSYS.RDF_VALUE$表で全文索引を使用します。この関数は次の構文を使用します(orardf<http://xmlns.oracle.com/rdf/>に展開される組込みの接頭辞です)。

orardf:textContains(variable, pattern)

orardf:textContainsへの最初の引数はローカル変数(つまり、orardf:textContainsフィルタを含むBGPに存在する変数)である必要があり、2つ目の引数は一定のプレーン・リテラルである必要があります。

たとえば、orardf:textContains(x, y)は、xが式yと一致する場合にtrueを戻します(yはOracle Text SQL演算子CONTAINSの有効な式です)。そのような式の詳細は、『Oracle Textリファレンス』を参照してください。

orardf:textContainsを使用する前に、RDFネットワークのOracle Text索引を作成する必要があります。そのような索引を作成するには、SEM_APIS.ADD_DATATYPE_INDEXプロシージャを次のように起動します。

EXECUTE SEM_APIS.ADD_DATATYPE_INDEX('http://xmlns.oracle.com/rdf/text');

orardf:textContains(?x, "%abc%")のようなワイルドカード検索のパフォーマンスは、プリフィックス索引と部分文字列索引を使用することで向上します。次の任意のオプションをSEM_APIS.ADD_DATATYPE_INDEXプロシージャに含めることができます。

  • prefix_index=true - プリフィックス索引の追加

  • prefix_min_length=<number> – プリフィックス索引トークンの最小長さ

  • prefix_max_length=<number> – プリフィックス索引トークンの最大長さ

  • substring_index=true - 部分文字列索引の追加

Oracle Textの索引付け要素の詳細は、『Oracle Textリファレンス』を参照してください。

テキスト索引のあるセマンティク・ネットワークに対して大規模バルク・ロードを実行する場合、テキスト索引を削除してバルク・ロードを実行してからテキスト索引を再作成すると、ロード時間全体が短縮される可能性があります。データ型索引の詳細は、「データ型索引の使用」を参照してください。

テキスト索引を作成すると、SEM_MATCH問合せでorardf:textContains FILTER関数を使用できます。例1-77では、orardf:textContainsを使用して、名前が文字AまたはBで始まるすべての祖父を検索しています。

例1-77 全文検索

SELECT x, y, n
  FROM TABLE(SEM_MATCH(
    '{ ?x :grandParentOf ?y . ?x rdf:type :Male . ?x :name ?n 
       FILTER (orardf:textContains(?n, " A% | B% ")) }',
    SEM_Models('family'),
    SEM_Rulebases('RDFS','family_rb'), 
    SEM_ALIASES(SEM_ALIAS('','http://www.example.org/family/')),
          null));

例1-78 orardf:textScore

副演算子orardf:textScoreorardf:textContainsと組み合わせて使用することで、結果をテキスト一致の程度でランク付けできます。ただし、orardf:textScoreの使用には制限があります。orardf:textScore呼び出しは、対応するorardf:textContains FILTERを含んでいる基本のグラフ・パターンの、すぐ外側にあるSELECT句のSELECT式として記述されている必要があります。その後は、このSELECT式の別名を、問合せの他の箇所で使用することができます。さらに、REWRITE=F問合せヒントを、SEM_MATCHのoptions引数で使用する必要があります。

次の例では、スコアが0.5を超えるテキスト一致を探しています。ここで、orardf:textContainsには呼出しIDを付加して、同じ呼出しIDを持つorardf:textScore呼出しと結び付けられるようにする必要があることに注意してください。呼び出しIDは任意の整数であり、主演算子をその副演算子と照合するために使用されます。

SELECT x, y, n, scr
  FROM TABLE(SEM_MATCH(
    'SELECT *
     WHERE {
       { SELECT ?x ?y ?n (orardf:textScore(123) AS ?scr)
         WHERE { 
           ?x :grandParentOf ?y . ?x rdf:type :Male . ?x :name ?n 
           FILTER (orardf:textContains(?n, " A% | B% ", 123)) }
       }
       FILTER (?scr > 0.5)
     }',
    SEM_Models('family'),
    SEM_Rulebases('RDFS','family_rb'), 
    SEM_ALIASES(SEM_ALIAS('','http://www.example.org/family/')),           
    null,
    null,
    ' REWRITE=F '));

例1-79 orardf:like

負荷が大きくないテキスト検索では、orardf:like関数を使用することができます。その場合、Oracle SQLのLIKE演算子を使用した単純なテストパターン照合が行われます。orardf:like関数の構文は次のとおりです。

orardf:like(string, pattern

orardf:likeの最初の引数には任意の変数またはRDF語句を指定できます。それに対してorardf:Containsの最初の引数はローカル変数でなければなりません。orardf:likeの最初の引数がURIである場合、照合はURIの接尾辞のみを対象にして行われます。2つ目の引数にはパターン式を指定する必要があります。このとき、次の特殊パターン一致文字を含めることができます。

  • パーセント記号(%)は0個以上の文字を表します。

  • アンダースコアはちょうど1文字を表します。

次の例では、パーセント記号(%)をワイルドカードとして使用して、URIがJaで始まるすべての祖父母を検索しています。

SELECT x, y, n
  FROM TABLE(SEM_MATCH(
    '{ ?x :grandParentOf ?y . ?y :name ?n 
        FILTER (orardf:like(?x, "Ja%")) }',
    SEM_Models('family'),
    SEM_Rulebases('RDFS','family_rb'), 
    SEM_ALIASES(SEM_ALIAS('','http://www.example.org/family/')),
    null));

次の例では、アンダースコア(_)をワイルドカードとして使用して、名前がJで始まり、その後に2文字が続いてkで終わる、すべての孫を検索しています。

SELECT x, y, n
  FROM TABLE(SEM_MATCH(
    '{ ?x :grandParentOf ?y . ?y :name ?n 
        FILTER (orardf:like(?n, "J__k")) 
    }',
    SEM_Models('family'),
    SEM_Rulebases('RDFS','family_rb'), 
    SEM_ALIASES(SEM_ALIAS('','http://www.example.org/family/')),
    null));

orardf:likeの実行効率を高めるために、SEM_APIS.ADD_DATATYPE_INDEXプロシージャを使用し、http://xmlns.oracle.com/rdf/likeをデータ型URIとして、索引を作成できます。この索引によって、最初の引数がローカル変数で、かつ検索パターンの前にある文字がワイルドカードでない場合に、問合せを高速化することができます。ここで基礎となっている索引は、VARCHAR型関数に対する単純な関数ベースのBツリー索引であるため、完全なOracle Text索引よりも保守とストレージに要するコストが低く抑えられます。orardf:likeは、次のようにして作成します。

EXECUTE SEM_APIS.ADD_DATATYPE_INDEX('http://xmlns.oracle.com/rdf/like');

1.6.11 空間のサポート

RDFセマンティク・グラフは、OGC GeoSPARQL標準を介して、およびOracle固有のSPARQL拡張機能を介して空間ジオメトリ・データの記憶域および問合せをサポートしています。ジオメトリ・データはorageo:WKTLiteralogc:wktLiteralまたはogc:gmlLiteral型付きリテラルとして格納可能で、空間操作用のいくつかの問合せ関数を使用してジオメトリ・データを問い合せることができます。パフォーマンス向上のための空間索引付けも、サポートされます。

orageo<http://xmlns.oracle.com/rdf/geo/>に展開される組込み接頭辞、ogc<http://www.opengis.net/ont/geosparql#>に展開される組込み接頭辞、ogcf<http://www.opengis.net/def/function/geosparql>に展開される組込み接頭辞です。

1.6.11.1 OGC GeoSPARQLのサポート

RDFセマンティク・グラフは、Well-Known Text (WKT)シリアライズとシンプル・フィーチャのリレーション・ファミリを使用して、OGC GeoSPARQL標準(http://www.opengeospatial.org/standards/geosparql)に準拠する次のクラスをサポートします。

  • コア

  • トポロジ・ボキャブラリ拡張(シンプル・フィーチャ)

  • ジオメトリ拡張(WKT、1.2.0)

  • ジオメトリ・トポロジ拡張(シンプル・フィーチャ、WKT、1.2.0)

  • RDFS伴意拡張(シンプル・フィーチャ、WKT、1.2.0)

GeoSPARQLを使用した空間データの表現および問合せの詳細は、以降の項で説明します。

1.6.11.2 RDFでの空間データの表現

空間ジオメトリは、RDFでorageo:WKTLiteralogc:wktLiteralまたはogc:gmlLiteral型付きリテラルとして表現できます。

例1-80 orageo:WKTLiteralとして表現される空間点ジオメトリ

次の例では、単純な点ジオメトリのorageo:WKTLiteralエンコーディングを示します。

"Point(-83.4 34.3)"^^<http://xmlns.oracle.com/rdf/geo/WKTLiteral>

例1-81 ogc:wktLiteralとして表現される空間点ジオメトリ

次の例では、前の例と同じ点のogc:wktLiteralエンコーディングを示します。

"Point(-83.4 34.3)"^^<http://www.opengis.net/ont/geosparql#wktLiteral>

orageo:WKTLiteralogc:wktLiteralエンコーディングはどちらも、オプションの空間参照システムURIと、それに続くWell-Known Text(WKT)文字列(ジオメトリ値をエンコードする)で構成されます。空間参照システムURIとWKT文字列は、空白文字で分離する必要があります。(このドキュメントでは、ジオメトリ・リテラルという用語で、orageo:WKTLiteralogc:wktLiteral型付きリテラルの両方を指しています。)

サポートされる空間参照システムURIは、<http://www.opengis.net/def/crs/EPSG/0/{srid}>という形式を取ります({srid}は、European Petroleum Survey Group (EPSG)によって定義される有効な空間参照システムIDです)。EPSGジオメトリック・パラメータ・データセットに含まれないURIの場合、使用される空間参照システムURIは、<http://xmlns.oracle.com/rdf/geo/srid/{srid}>という形式を取ります({srid}は、Oracle Spatial and Graphの有効な空間参照システムIDです)。ジオメトリ・リテラル値に空間参照システムURIが含まれない場合、デフォルトの空間参照システムのWGS84経度-緯度(URI <http://www.opengis.net/def/crs/OGC/1.3/CRS84>)が使用されます。問合せ文字列内にジオメトリ・リテラル値が見つかると、同じデフォルトの空間参照システムが使用されます。

例1-82 ogc:gmlLiteralとして表現される空間点ジオメトリ

次の例では、点ジオメトリのogc:gmlLiteralエンコーディングを示します。

"<gml:Point srsName=\"urn:ogc:def:crs:EPSG::8307\" xmlns:gml=\"http://www.opengis.net/gml\"><gml:posList srsDimension=\"2\">-83.4 34.3</gml:posList></gml:Point>"^^<http://www.opengis.net/ont/geosparql#gmlLiteral>

ogc:gmlLiteralエンコーディングは、GM_Objectのサブタイプを実装するGMLスキーマの有効な要素で構成されます。WKTリテラルとは異なり、GMLエンコーディングには空間参照システム情報が明示的に含まれるため、空間参照システムURIの接頭辞が不要です。

いくつかのジオメトリ・タイプは、点、線ストリング、ポリゴン、多面体面、三角形、TIN、複数点、複数の線ストリング、複数のポリゴンおよびジオメトリ・コレクションを含む、ジオメトリ・リテラル値として表現できます。2次元ジオメトリでは、1ジオメトリ当たり最大500,000の頂点がサポートされます。

例1-83 orageo:WKTLiteral値を使用してエンコードされる空間データ

次の例では、orageo:WKTLiteral値を使用してエンコードされるRDF空間データ(N-triple形式)をいくつか示します。この例では、最初の2つのジオメトリ(lot1内)はデフォルトの座標系(SRID 8307)を使用し、その他の2つのジオメトリ(lot2内)はSRID 8265を指定しています。

# spatial data for lot1 using the default WGS84 Longitude-Latitude spatial reference system
<urn:lot1> <urn:hasExactGeometry> "Polygon((-83.6 34.1, -83.6 34.5, -83.2 34.5, -83.2 34.1, -83.6 34.1))"^^<http://xmlns.oracle.com/rdf/geo/WKTLiteral> .
<urn:lot1> <urn:hasPointGeometry> "Point(-83.4 34.3)"^^<http://xmlns.oracle.com/rdf/geo/WKTLiteral> .
# spatial data for lot2 using the NAD83 Longitude-Latitude spatial reference system
<urn:lot2> <urn:hasExactGeometry> "<http://xmlns.oracle.com/rdf/geo/srid/8265> Polygon((-83.6  34.1, -83.6 34.3, -83.4 34.3, -83.4 34.1, -83.6 34.1))"^^<http://xmlns.oracle.com/rdf/geo/WKTLiteral> .
<urn:lot2> <urn:hasPointGeometry> "<http://xmlns.oracle.com/rdf/geo/srid/8265> Point(-83.5 34.2)"^^<http://xmlns.oracle.com/rdf/geo/WKTLiteral> .

詳細は、『Oracle Spatial and Graph開発者ガイド』の座標系(空間参照システム)に関する章を参照してください。Open Geospatial Consortium (OGC)のシンプル・フィーチャのドキュメント(http://www.opengeospatial.org/standards/sfa)で、WKTジオメトリ表現に関する資料も参照してください。

1.6.11.3 ジオメトリの検証

空間データを操作する前に、RDFモデルに無効なジオメトリ・リテラルが格納されていないことを確認する必要があります。プロシージャSEM_APIS.VALIDATE_GEOMETRIESを使用すると、RDFモデルのジオメトリを検証できます。ジオメトリは、入力SRIDおよび許容値を使用して検証します。(SRIDおよび許容値の詳細は、「空間データの索引付け」を参照してください。)

無効なジオメトリが存在する場合、{model_name}_IVG$という名前の表がユーザー・スキーマに作成されます({model_name}は指定したRDFモデルの名前です)。このような表には、無効なジオメトリ・リテラルごとに、MDSY.RDF_VALUE$表のジオメトリ・リテラルのvalue_id、ジオメトリが有効でない理由を説明するエラー・メッセージおよびジオメトリが修正できる場合は修正されたジオメトリ・リテラルが含まれます。ジオメトリの検証の詳細は、Oracle Spatial and GraphサブプログラムSDO_GEOM.VALIDATE_GEOMETRY_WITH_CONTEXTおよびSDO_GEOM.VALIDATE_LAYER_WITH_CONTEXTのリファレンス情報を参照してください。

例1-84 モデルのジオメトリの検証

次の例では、SRID=8307およびtolerance=0.1を使用してモデルmを検証します。

-- Validate
EXECUTE sem_apis.validate_geometries(model_name=>'m',SRID=>8307,tolerance=>0.1);
-- Check for invalid geometries
SELECT original_vid, error_msg, corrected_wkt_literal FROM M_IVG$;
1.6.11.4 空間データの索引付け

任意のSPARQL拡張関数(「空間データの問合せ」を参照)を使用して空間データを問い合せる前に、SEM_APIS.ADD_DATATYPE_INDEXプロシージャをコールしてRDFネットワークに空間索引を作成する必要があります。

空間索引を作成する場合、次の情報を指定する必要があります。

  • SRID: 空間索引を作成する空間参照システムのID。Oracle Spatial and Graphからの任意の有効な空間参照システムIDを、SRID値として使用できます。

  • TOLERANCE: 空間索引の許容値。許容値は、2つの点が同じ点とみなされるためにどの程度近接している必要があるかを示す正数です。この値の単位は、使用されるSRIDのデフォルト単位によって決定されます(たとえば、WGS84経度/緯度の場合はメートル)。許容差は、『Oracle Spatial and Graph開発者ガイド』で詳細に説明されています。

  • DIMENSIONS: 空間索引のテキスト文字列エンコーディングの次元情報。各次元は、カンマ区切りの一連の3つの値(名前、最小値および最大値)で表現されます。各次元をカッコで囲み、それらの次元のセットを外側のカッコで囲みます。

例1-85 RDFデータ上の空間データ型索引の追加

例1-85では、RDFネットワーク上の空間データ型索引を追加し、この座標系を使用する空間データの索引付けに関する、WGS84経度-緯度空間参照システム、10メートルの許容差値、推奨次元を指定しています。TOLERANCE、SRIDおよびDIMENSIONSキーワードの大/小文字は区別され、<http://xmlns.oracle.com/rdf/geo/WKTLiteral>に対してデータ型索引を作成すると、<http://www.opengis.net/ont/geosparql#wktLiteral>ジオメトリ・リテラルにも索引付けされ、この逆も同様に行われます(つまり、<http://www.opengis.net/ont/geosparql#wktLiteral>に対してデータ型索引を作成すると<http://xmlns.oracle.com/rdf/geo/WKTLiteral>ジオメトリ・リテラルにも索引付けされます)。

EXECUTE sem_apis.add_datatype_index('http://xmlns.oracle.com/rdf/geo/WKTLiteral',  options=>'TOLERANCE=10 SRID=8307 DIMENSIONS=((LONGITUDE,-180,180) (LATITUDE,-90,90))');

RDFネットワークについては1つの空間データ型索引のみサポートされます。RDFネットワークに格納されるジオメトリ・リテラル値は、索引に使用される空間参照システムに自動的に正規化されるため、単一の空間索引では複数の空間参照システムからのジオメトリ・リテラル値を同時にサポートできます。この座標変換は、索引付けと空間の計算に対して透過的に行われます。ジオメトリ・リテラル値がSEM_MATCH問合せから戻されるときは、元の未変換のジオメトリが戻されます。

空間索引付けの詳細は、『Oracle Spatial and Graph開発者ガイド』で空間データの索引付けおよび問合せに関する章を参照してください。

1.6.11.5 空間データの問合せ

SEM_MATCHで空間問合せを実行するために、複数のSPARQL拡張関数を使用できます。たとえば、空間RDFデータでは、ジオメトリの領域と境界線(長さ)、2つのジオメトリ間の距離、およびジオメトリの重心と最小外接矩形を検出することや、ジオメトリ間の様々な位相関係を確認することができます。

「空間問合せのSEM_MATCHサポート」には、利用可能な関数のリファレンスおよび使用法に関する情報が記載されています。

  • GeoSPARQLの関数

  • Oracle固有の関数

1.6.11.6 GeoSPARQL問合せとのロング・リテラルの使用

ジオメトリ・リテラルは非常に長くなることがあり、それらを表すのにCLOBの使用が必要になります。CLOB定数は、SEM_MATCH問合せで直接使用することはできません。しかし、ユーザー定義のSPARQL関数を使用してCLOB定数をSEM_MATCH問合せにバインドできます。

次の例では、一時表を使用してこれを行っています。

例1-86 SPARQL問合せへのCLOB定数のバインド

conn rdfuser/<password>;

-- Create temporary table
create global temporary table local_value$(
 VALUE_TYPE 	 VARCHAR2(10),
 VALUE_NAME     VARCHAR2(4000),
 LITERAL_TYPE	 VARCHAR2(1000),
 LANGUAGE_TYPE	 VARCHAR2(80),
 LONG_VALUE 	 CLOB)
on commit preserve rows;

-- Create user-defined function to transform a CLOB into an RDF term
CREATE OR REPLACE FUNCTION myGetClobTerm
RETURN MDSYS.SDO_RDF_TERM
AS
  term	     SDO_RDF_TERM;
BEGIN
  select sdo_rdf_term(
      value_type,
      value_name,
      literal_type,
      language_type,
      long_value)
  into term
  from local_value$
  where rownum < 2;

  RETURN term;
END;
/

-- Insert a row with CLOB geometry
insert into local_value$(value_type,value_name,literal_type,language_type,long_value)
values ('LIT','','http://www.opengis.net/ont/geosparql#wktLiteral','','Some_CLOB_WKT');

-- Use the CLOB constant in a SEM_MATCH query
SELECT cdist
FROM table(sem_match(
'{ ?cdist ogc:asWKT ?cgeom 
   FILTER (
     orageo:withinDistance(?cgeom, oraextf:myGetClobTerm(), 200, "M")) }'
,sem_models('gov_all_vm')
,null, null,null, null, ' ALLOW_DUP=T '));

1.6.12 フラッシュバック問合せのサポート

フラッシュバック問合せを使用して、過去のデータを返すSEM_MATCH問合せを実行できます。TIMESTAMPまたはシステム変更番号(SCN)の値が、AS_OFヒントを介してSEM_MATCHへ渡されます。AS_OFヒントは、次のいずれかの書式で指定できます。

  • AS_OF[TIMESTAMP,<TIMESTAMP_VALUE>] (ここで、<TIMESTAMP_VALUE>は「YYYY/MM/DD HH24:MI:SS.FF」という形式の、有効なタイムスタンプ文字列です。)

  • AS_OF[SCN,<SCN_VALUE>] (ここで<SCN_VALUE>は有効なSCNです。)

AS_OFヒントは、指定したモデルのトリプルを格納している問合せ対象の表またはビューに対してフラッシュバック問合せ(SELECT AS OF)を実行するために、内部変換されます。これにより、それ以前に存在していたモデルに対する問合せが可能になります。この機能を動作させるには、呼出しの際に、問合せの対象となるメタデータの表またはビューに対するフラッシュバック権限が必要です (ネイティブ・モデルに対するMDSYS.RDFM_model-nameビュー、仮想モデルに対するMDSYS.SEMU_virtual-model-nameおよびMDSYS.SEMV_virtual-model-name、およびRDFビュー・モデルの基礎となっているリレーショナル表)。たとえば、grant flashback on MDSYS.RDFM_FAMILY to rdfuserのようにします。

RDFデータでフラッシュバック問合せを使用する際の制限

パーティション表に対して、パーティションの追加や削除を行うと、以前のバージョンのパーティション表に対するフラッシュバック問合せが無効化されます。結果的に、ネイティブRDFモデルの作成または削除、あるいは伴意の作成または削除により、セマンティク・ネットワークにある以前のバージョンのネイティブRDFモデルすべてに対するフラッシュバック問合せが無効になります。したがって、セマンティク・ネットワークでフラッシュバック問合せを使用している場合、そうした操作は確実に管理する必要があります。

例1-87 TIMESTAMPを使用したフラッシュバック問合せ

次の例では、AS_OF句を使用してTIMESTAMPを定義しています。

SELECT x, name
  FROM TABLE(SEM_MATCH(
    '{ ?x :name ?name }',
    SEM_Models('family'),
    null, 
    SEM_ALIASES(SEM_ALIAS('','http://www.example.org/family/')),
    null,null,' AS_OF=[TIMESTAMP,2016/05/02 13:06:03.979546]'));

例1-88 SCNを使用したフラッシュバック問合せ

次の例では、AS_OF句を使用してSCNを指定しています。

SELECT x, name
  FROM TABLE(SEM_MATCH(
    '{ ?x :name ?name }',
    SEM_Models('family'),
    null, 
    SEM_ALIASES(SEM_ALIAS('','http://www.example.org/family/')),
    null,null,' AS_OF=[SCN,1429849]'));

1.6.13 問合せパフォーマンスのベスト・プラクティス

この項では、SEM_MATCH表関数を使用してセマンティク・データを問い合せる場合に推奨される方法について説明します。次のサブセクションが含まれます:

1.6.13.1 xsd:dateTime、xsd:dateおよびxsd:timeを含むFILTER構成要素

デフォルトでは、SEM_MATCHは、xsd:date、xsd:timeおよびxsd:dateTimeの値の比較についてXMLスキーマ標準に準拠しています。この標準に従って2つのカレンダ値のc1とc2を比較すると(c1には明示的にタイムゾーンが指定され、c2にはタイムゾーンが指定されていません)、c2は[c2-14:00, c2+14:00]という間隔に変換されます。c2-14:00 <= c1 <= c2+14:00である場合、比較は未定義となり、常にfalseに評価されます。c1がこの間隔の外部にある場合、比較は定義されます。

ただし、このような比較(タイムゾーンを持つ値とタイムゾーンを持たない値)の評価に必要な追加のロジックによって、カレンダ値が関係するFILTER構成要素を含む問合せの速度が大幅に低下する可能性があります。問合せパフォーマンスを向上させるには、SEM_MATCH表関数のoptionsパラメータにFAST_DATE_FILTER=Tを指定することによって、この追加ロジックを無効にできます。FAST_DATE_FILTER=Tを指定すると、タイムゾーンのないカレンダ値については、すべてグリニッジ標準時(GMT)と想定されます。

FAST_DATE_FILTER=Tを使用すると、(1)データセットのすべてのカレンダ値がタイムゾーンを持つ場合も、(2)データセットのすべてのカレンダ値がタイムゾーンを持たない場合も、問合せの正確性には影響ありません

1.6.13.2 型付きリテラルを含むFILTER構成要素の関数ベース索引

FILTER構成要素を含むSEM_MATCH問合せの評価には、通常、RDF_VALUE$表に対して1つ以上のSQL関数の実行が必要になります。たとえば、フィルタ(?x < "1929-11-16Z"^^xsd:date)によって、SEM_APIS.GETV$DATETZVAL関数が呼び出されます。

型付きリテラルが関係するフィルタ条件を含む問合せのパフォーマンスを向上させるには、関数ベースの索引を使用できます。たとえば、xsd:date関数ベース索引によって、フィルタ(?x < "1929-11-16Z"^^xsd:date)の評価の速度が向上する場合があります。

これらの関数ベース索引の作成、変更および削除のために、便利なインタフェースが用意されています。詳細は、「データ型索引の使用」を参照してください。

ただし、MDSYS.RDF_VALUE$表にこれらの関数ベース索引が存在することで、バルク・ロード操作の速度は大幅に低下する可能性があります。多くの場合、索引付きのままバルク・ロードを実行する場合と比較すると、索引を削除し、バルク・ロードを実行してから索引を再作成する方が高速です。

1.6.13.3 関係式を含むFILTER構成要素

関係式を含むFILTER構成要素には次の推奨事項が適用されます。

  • sameCanonTerm拡張関数は、2つのRDF語句を同一性の面で比較する場合に最も効率的な方法です。これは、すべての場合にIDベースの比較ができるからです。

  • 標準のSPARQL機能を利用している場合、FILTER句内の2つの変数を比較するには、=または!=よりもsameTerm組込み関数の方が効率が良いため、(たとえば)可能なかぎり(?a = ?b)ではなくsameTerm(?a, ?b)を使用し、(?a != ?b)ではなく(!sameTerm(?a, ?b))を使用します。

  • FILTER式で値を比較するときは、否定の使用を減らすことによってパフォーマンスが向上する場合があります。たとえば、(?x <= "10"^^xsd:int)を評価する方が、式(!(?x > "10"^^xsd:int))を評価するよりも効率的です。

1.6.13.4 オプティマイザ統計と動的サンプリング

問合せオプティマイザに十分な統計を確保することは、優れた問合せパフォーマンスのために非常に重要です。通常は、SEM_PERF.GATHER_STATSプロシージャを使用して、セマンティク・ネットワークの基本的な統計が収集されていることを確認する必要があります(「SEM_PERFパッケージのサブプログラム」を参照)。

RDFデータ・モデル本来の柔軟性のため、静的情報ではSEM_MATCH問合せの最適実行計画が生成されない場合があります。通常、動的サンプリングでは、非常によい問合せ実行プランを生成できます。動的サンプリング・レベルは、optimizer_dynamic_samplingパラメータを使用してセッションまたはシステム・レベルで設定することも、dynamic_sampling(level) SQL問合せヒントを使用して個別の問合せレベルで設定することもできます。通常は3から6の間の動的サンプリング・レベルで試すことをお薦めします。動的サンプリングの統計の見積りの詳細は、『Oracle Database SQLチューニング・ガイド』を参照してください。

例1-89では、動的サンプリング・レベルが6のSQLヒントを使用しています。

例1-89 動的サンプリングのSQLヒント

SELECT /*+ DYNAMIC_SAMPLING(6) */ x, y
  FROM TABLE(SEM_MATCH(
    '{?x :grandParentOf ?y . 
      ?x rdf:type :Male . 
      ?x :birthDate ?bd }',
    SEM_Models('family'),
    SEM_Rulebases('RDFS','family_rb'), 
    SEM_ALIASES(SEM_ALIAS('','http://www.example.org/family/')),
    null, null, '' ));
1.6.13.5 複数パーティションの問合せ

複数のセマンティク・モデル、セマンティク・モデルと伴意、および仮想モデルの使用には、次の推奨事項が適用されます。

  • 複数のセマンティク・モデルに対して、またはセマンティク・モデルと伴意に対してSEM_MATCH問合せを実行する場合は、問い合せるすべてのモデルと伴意を含む仮想モデル(「仮想モデル」を参照)を作成して、この単一の仮想モデルを問い合せると、問合せパフォーマンスが向上する可能性があります。

  • ALLOW_DUP=T問合せオプションを使用します。このオプションを使用しない場合は、RDFデータの設定済セマンティクを保持するために、問合せ処理中に高コストな(処理に関して)重複除去ステップが必要になります。ただし、このオプションを使用した場合、重複除去ステップは実行されず、パフォーマンスが大幅に向上します。

1.6.13.6 OLTP索引圧縮によるシステムの圧縮

OLTP索引圧縮がサポートされるシステム(Exadataなど)では、セマンティク・ネットワークによって使用される一部のBツリー索引の圧縮率を向上させる機能を利用できます。

たとえば、DBAは次のコマンドを使用して、MDSYS.RDF_VAL_NAMETYLITLNG_IDX索引での圧縮スキームを接頭辞圧縮からOLTP索引圧縮に変更できます。

SQL> alter index mdsys.RDF_VAL_NAMETYLITLNG_IDX rebuild compress for oltp high;
1.6.13.7 無制限のプロパティ・パス表現

+および*プロパティ・パス演算子では、可能な場合には常に深度制限検索を使用する必要があります。*および+の深度制限実装のパフォーマンスは、大規模なグラフや関連性が高いグラフにおいてはCONNECT BYベースの実装を大幅に上回ります。深度制限10がデフォルトで使用されます。どのグラフでもグラフの直径を超えた深度制限は役立ちません。深度制限の設定の詳細は、「プロパティ・パス」を参照してください。

クラス階層が非常に深いオントロジに対してrdfs:subClassOf+を使用する後方連鎖スタイルの推論は、このルールの例外になることがあります。このようなケースでは、無制限のCONNECT BYベース評価のパフォーマンスが、非常に大きな深度制限(たとえば50)の深度制限評価よりもよくなることがあります。

1.6.13.8 ネストしたループによるプロパティ・パスのプッシュダウン

あるプロパティ・パスに対して無制限のCONNECT BY評価が実行される場合で、しかもそのプロパティ・パスのトリプル・パターンの主語が変数の場合、使用される可能性が最も高いのは、CONNECT BY WITHOUT FILTERING操作です。主語になっているその変数が、問合せ実行時に限られた数の値にバインドされているだけであれば、問合せの実行時にネストしたループを用いる方法(「過負荷のサービスにおけるネストしたループによるプッシュダウン」を参照)を選ぶと良い場合があります。その場合、プロパティ・パスをSERVICE句にプッシュダウンすることができます。またOVERLOADED_NL=Tヒントを使用できます。

たとえば、次に示すような問合せを考えてみます。ここで、無制限のプロパティ・パス検索{ ?s :hasManager+ ?x }はあるものの、トリプル{ ?s :ename "ADAMS" }?sに対して取り得る値の数は限られているものとします。

select s, x
from table(sem_match(
'PREFIX : <http://scott-hr.org#>
 SELECT *
 WHERE {
   ?s :ename "ADAMS" .
   ?s :hasManager+ ?x .
 }',
sem_models('scott_hr_data'),
null,null,null,null,'  ALL_MAX_PP_DEPTH(0) '));

この問い合わせは、ネストしたループで実行されるように書き換えることができます。ここで、サービス・グラフで指定されたモデルは、SEM_MATCH呼び出しで指定されたモデルと同じである点に注意してください。

select s, x
from table(sem_match(
'PREFIX : <http://scott-hr.org#>
 SELECT *
 WHERE {
   ?s :ename "ADAMS" .
   service oram:scott_hr_data { ?s :hasManager+ ?x . }
 }',
sem_models('scott_hr_data'),
null,null,null,null,'  ALL_MAX_PP_DEPTH(0) OVERLOADED_NL=T '));

ネストしたループを用いたこの例では、{ ?s :hasManager_ ?x }?sの値ごとに1回ずつ評価され、評価のたびに定数が?sに代入されます。定数が主語の位置にあることで、CONNECT BY WITH FILTERING操作が可能になります。この操作により、通常はパフォーマンスが大幅に向上します。

1.6.13.9 グループ化と集計

MINMAXおよびGROUP_CONCAT集計では、不均一なタイプ(たとえば、MAX(?x))の入力についてSPARQLセマンティクを完全にキャプチャするために特別なロジックが必要です。均一入力タイプをコンパイル時に判別できるケース(たとえば、MAX(STR(?x)) - プレーン・リテラル入力)では、組込みSQL集計の最適化を使用できます。通常は、このような最適化によってパフォーマンスが1桁向上します。次のケースは最適化されます。

  • MIN/MAX(<plain literal>)

  • MIN/MAX(<numeric>)

  • MIN/MAX(<dateTime>)

  • GROUP_CONCAT(<plain literal>)

図1-90はMIN/MAX(<numeric>)最適化を使用しています。

例1-90 集計の最適化

SELECT dept, minSal, maxSal
  FROM TABLE(SEM_MATCH(
    'SELECT ?dept (MIN(xsd:decimal(?sal)) AS ?minSal) (MAX(xsd:decimal(?sal)) AS ?maxSal)
     WHERE
       {?x :salary ?y . 
        ?x :department ?dept }
     GROUP BY ?dept',
    SEM_Models('hr_data'),
    null, null, null, null, '' ));
1.6.13.10 バインド変数の使用によるコンパイル時間の短縮

問合せによっては、問合せの実行よりも問合せのコンパイルにコストがかかることがあり、小規模な問合せでは、所定の作業量に対するスループットがこれにより制限を受ける場合があります。実行すべき各問合せで異なる部分が定数のみの場合、セッションのコンテキストに依存するバインド変数を使用して、コンパイルのステップを省略することができます。

次の例では、セッション・コンテキストをユーザー定義のSPARQL関数と組み合わせて使用し、SEM_MATCH問合せを1回コンパイルしてからその問合せを異なる定数で実行する方法を示します。ここでの基本的な考え方は、セッション・コンテキストからRDF語句を読み取り、それを返すユーザー定義の関数を作成することにあります。この関数では、実行時にSEM_MATCH問合せによりRDF語句の値が読み取られます。したがって、セッション・コンテキスト変数が変化すると、まったく同じSEM_MATCH問合せでも、異なる値が生成されることになります。

conn / as sysdba;
grant create any context to testuser;

conn testuser/testuser;

create or replace package MY_CTXT_PKG as  
  procedure set_attribute(name varchar2, value varchar2);  
  function get_attribute(name varchar2) return varchar2;  
end MY_CTXT_PKG;  
/

create or replace package body MY_CTXT_PKG as  
  procedure set_attribute(  
    name varchar2,  
    value varchar2  
  ) as  
  begin  
    dbms_session.set_context(namespace => 'MY_CTXT',  
                             attribute => name,  
                             value     => value );
  end;  

  function get_attribute(  
    name varchar2  
  ) return varchar2 as  
  begin  
    return sys_context('MY_CTXT', name);  
  end;  
end MY_CTXT_PKG;  
/

create or replace function myCtxFunc(  
  params in MDSYS.SDO_RDF_TERM_LIST  
) return MDSYS.SDO_RDF_TERM  
as  
  name varchar2(4000);  
  arg  MDSYS.SDO_RDF_TERM;  
begin  
  arg := params(1);  
  name := arg.value_name;  
  return MDSYS.SDO_RDF_TERM(my_ctxt_pkg.get_attribute(name));  
end;  
/  

CREATE OR REPLACE CONTEXT MY_CTXT using TESTUSER.MY_CTXT_PKG;

-- Set a value
exec MY_CTXT_PKG.set_attribute('value','<http://www.example.org/family/Martha>');

-- Query using the function
-- Note the use of HINT0={ NON_NULL } to allow the most efficient join
SELECT s, p, o
  FROM TABLE(SEM_MATCH(
    'SELECT ?s ?p ?o
     WHERE {
       BIND (oraextf:myCtxFunc("value") # HINT0={ NON_NULL } 
             AS ?s)
       ?s ?p ?o }',
    SEM_Models('family'),
    null,
    SEM_ALIASES(SEM_ALIAS('','http://www.example.org/family/')),
    null));

-- Set another value
exec MY_CTXT_PKG.set_attribute('value','<http://www.example.org/family/Sammy>');

-- Now the same query runs for Sammy without recompiling
SELECT s, p, o
  FROM TABLE(SEM_MATCH(
    'SELECT ?s ?p ?o
     WHERE {
       BIND (oraextf:myCtxFunc("value") # HINT0={ NON_NULL } 
             AS ?s)
       ?s ?p ?o }',
    SEM_Models('family'),
    null,
    SEM_ALIASES(SEM_ALIAS('','http://www.example.org/family/')),
    null));
1.6.13.11 非NULL式ヒント

共通の変数を持つ複数のグラフ・パターンを用いて無制限になる可能性のある結合を行う場合、パフォーマンスの低下を防ぐために、NULL値を処理するより複雑な結合条件が必要になります。無制限な値は、SELECT式、バインド、OPTIONAL句およびUNIONで発生する可能性があります。多くの場合、SELECT式でNULL値が発生することは考えられません。そのような場合には、インラインのHINT0={ NON_NULL }ヒントを用いて特定のSELECT式がNULL値にならないことを明示するか、DISABLE_NULL_EXPR_JOIN問合せオプションを使用して、すべてのSELECT式でNULL以外の値が生成されることを示すことで、問合せのパフォーマンスが大幅に向上します。

次の例では、変数?fulltitleが常に結合の両端で制限されていることが、グローバルなDISABLE_NULL_EXPR_JOINヒントにより明示されています。(「インライン問合せオプティマイザ・ヒント」も参照してください。)

SELECT s, t
  FROM TABLE(SEM_MATCH(
    'SELECT * WHERE {
       { SELECT ?s (CONCAT(?title, ". ", ?fullname) AS ?fulltitle)
         WHERE { ?s :fullname ?fullname .
                 ?s :title ?title }
       }
       { SELECT ?t (CONCAT(?title, ". ", ?fname, " ", ?lname) AS ?fulltitle)
         WHERE { 
         ?t :fname ?fname .
         ?t :lname ?lname . 
         ?t :title ?title } 
       } 
     }',
    SEM_Models('family'),
    SEM_Rulebases('RDFS','family_rb'), 
    SEM_ALIASES(SEM_ALIAS('','http://www.example.org/family/')),
    null,
    null,
    ' DISABLE_NULL_EXPR_JOIN '));

1.6.14 SEM_MATCH使用時の特別な考慮事項

次の考慮事項は、SEM_MATCHを使用してRDFセマンティク・グラフで実行されるSPARQL問合せに適用されます。

  • 値の割当て

    • 値割り当てのソースで未定義の変数が参照されると、コンパイル時にエラーが発生します。

  • グループ化と集計

    • 非グループ化変数(グループ化に使用されないため、射影には妥当でない問合せ変数)は、値割り当てのターゲットとして再利用できません。

    • 数値以外の値は、AVGおよびSUM集計によって無視されます。

    • デフォルトでは、SEM_MATCHは、グラフ・パターンが一致しない集計問合せの場合に行を返しません。W3C仕様では、このケースでは1つのnull行が必要です。STRICT_AGG_CARD=T問合せオプションを使用すると動作がW3Cに準拠しますが、パフォーマンスがわずかに低下します。

  • ORDER BY

    • SEM_MATCHでSPARQL ORDER BYを使用する場合、取り囲んでいるSQLブロック全体を通じて目的の順序を維持するためには、格納側のSQL問合せをSEM$ROWNUMで並べ替える必要があります。

  • 数値の計算

    • ネイティブのOracleのNUMBER型はすべての演算処理のために内部的に使用され、すべての算術演算の結果はxsd:decimalとしてシリアライズされます。ネイティブのOracleのNUMBER型は、BINARY_FLOATおよびBINARY_DOUBLEよりも正確です。組込みデータ型NUMBERの詳細は、『Oracle Database SQL言語リファレンス』を参照してください。

    • ゼロで除算した場合は、バインドされていない値が生成されるのではなく、ランタイム・エラーが発生します。

  • 否定

    • 潜在的にバインドされていない変数を参照するEXISTSおよびNOT EXISTSフィルタは、次のコンテキストではサポートされません。

      • GROUP BY内の別名のない式

      • 集計への入力

      • ORDER BY内の式

      • OPTIONALグラフ・パターン内に出現しない変数も参照するOPTIONALグラフ・パターン内のFILTER式

      最初の3つのケースは、BIND句またはSELECT式を使用して変数にEXISTSまたはNOT EXISTSフィルタの結果を最初に割り当てることで実現できます。

      これらの制限は、明確にバインドされた変数のみを参照するEXISTSおよびNOT EXISTSフィルタには、当てはまりません

  • 空白ノード

    • 空白ノードは、グラフ・パターン内ではサポートされません。

    • BNODE(literal)関数は、同じリテラル引数でコールされるたびに、同じ空白ノード値を戻します。

  • プロパティ・パス

    • 無制限の演算子+および*は、パフォーマンスの理由からデフォルトでは10ホップの深度制限を使用します。深度制限を0に設定すると、この動作を完全に無制限の検索に変更できます。詳細は、「プロパティ・パス」を参照してください。

  • ロング・リテラル(CLOB)

    • SPARQLの関数と集計は、デフォルトではロング・リテラルをサポートしていません。

    • CLOB_EXP_SUPPORT=T問合せオプションを指定すると、SPARQL関数(IF、COALESCE、STRLANG、STRDT、SUBSTR、STRBEFORE、STRAFTER、CONTAINS、STRLEN、STRSTARTS、STRENDS)でのロング・リテラルのサポートが有効になります。

    • CLOB_AGG_SUPPORT=T問合せオプションを指定すると、集計(MIN、MAX、SAMPLE、GROUP_CONCAT)でのロング・リテラルのサポートが有効になります。

  • RDFリテラルの正規化

    • デフォルトでは、SPARQL関数から返されるRDFリテラルと、値割当て文(BIND、SELECT式、GROUP BY式)で使用される定数RDFリテラルは正規化されます。この動作は、SPARQL 1.1の「D-Entailment Regime」と一致しています。

    • 正規化を無効にするにはPROJ_EXACT_VALUES=T問合せオプションを使用します。

1.7 SEM_APIS.SPARQL_TO_SQL関数を使用したセマンティク・データの問合せ

SEM_APIS.SPARQL_TO_SQL関数をSEM_MATCH表関数の代わりに使用してセマンティク・データの問い合わせができます。

SEM_APIS.SPARQL_TO_SQL関数は、SEM_MATCH表関数の代替になるものとして用意されています。アプリケーション開発者は、これを利用してSPARQL問合せをSQLに翻訳することができます。これは、SEM_MATCHを実行した場合と同じSQL翻訳です。生成されたSQL翻訳は、その他のSQL文字列と同じ方法で実行可能です(たとえばPL/SQLのEXECUTE IMMEDIATEや、JavaアプリケーションのJDBC)。

SEM_APIS.SPARQL_TO_SQLに対する最初の(sparql_query)パラメータで、SPARQL問合せ文字列を指定します。これはSEM_MATCHの問合せ引数に相当します。ただしこの場合、sparql_queryは、CLOB型であり、4000バイト(VARCHARが有効になっている場合は32Kバイト)を超える長さの問合せ文字列を使用できます。その他の引数はすべて、SEM_MATCHの対応する引数とまったく同等です(「セマンティク・データに対する問合せでのSEM_MATCH表関数の使用」を参照してください)。SEM_APIS.SPARQL_TO_SQLで返される問合せ文字列によって、SEM_MATCHを同じ引数で実行したときと同じ結果の列が生成されます。

次に示すPL/SQLの一部分は、SEM_APIS.SPARQL_TO_SQL関数を使用した例です。

DECLARE
  c           sys_refcursor;
  sparql_stmt clob;
  sql_stmt    clob;
  x_value     varchar2(4000);
BEGIN
  sparql_stmt := 
    'SELECT ?x
     WHERE {
       ?x :grandParentOf ?y . 
       ?x rdf:type :Male
     }';

  sql_stmt := sem_apis.sparql_to_sql(
                sparql_stmt,
                sem_models('family'),
                SEM_Rulebases('RDFS','family_rb'),
                SEM_ALIASES(SEM_ALIAS('','http://www.example.org/family/')),
                null,
                ' PLUS_RDFT=VC ');

  open c for 'select x$rdfterm from(' || sql_stmt || ')';
  loop
    fetch c into x_value;
    exit when c%NOTFOUND;
    
    dbms_output.put_line('x_value: ' || x_value);    
  end loop;
  close c;

END;
/

1.7.1 SEM_APIS.SPARQL_TO_SQLによるバインド変数の使用

SEM_APIS.SPARQL_TO_SQL関数を使用すると、PL/SQLおよびJDBCのバインド変数を使用できます。これは、SEM_APIS.SPARQL_TO_SQLから返されるSQL翻訳に、ANYTYPE表関数への呼出しが含まれていないためです。基本的な仕組みとして、USE_BIND_VAR=PLSQLまたはUSE_BIND_VAR=JDBC問合せオプションが指定されている場合に、単純なSPARQL BIND句が、JDBCかPL/SQLのバインド変数いずれかに変換されます。単純なSPARQL BIND句とは、BIND (<constant> AS ?var)の形式を持つものです。

バインド変数オプションが指定されている場合、SQL翻訳には、変換されたSPARQL問合せ変数各々に対して2つのバインド変数が含まれることになります。1つは値ID、もう1つはRDF語句文字列です。値ID(MDSYS.RDF_VALUE$表から)を1番目のバインド値として、またRDF語句文字列を2番目のバインド値として指定することで、RDF語句をSPARQL問合せ変数の代替として用いることができます。パフォーマンス上の理由から、制限内のRDF語句に対する値IDが必要です。一般的なワークフローでは、RDF語句に対する値IDをMDSYS.RDF_VALUE$表から(またはSEM_APIS.RES2VIDで)で検索し、得られたIDとRDF語句を、翻訳されたSQLにバインドします。

1つの問合せで複数の問合せ変数がバインド変数に変換されることがあります。そうした場合、バインド変数は、SPARQL問合せ文字列のSPARQL BIND句と同じ順序でSQL翻訳に現れます。つまり、1番目のBIND句に対応するIDと語句のペアが最初にバインドされ、2番目のBIND句に対応するIDと語句のペアが2番目にバインドされます。

次に示す例では、PL/SQLブロックから、SEM_APIS.SPARQL_TO_SQLに対するバインド変数が使用されています。ダミーのバインド変数?nが宣言されています。

DECLARE
  sparql_stmt clob;
  sql_stmt    clob;
  cur         sys_refcursor;
  vid         number;
  term        varchar2(4000);
  c_val       varchar2(4000);
BEGIN
  -- Add a dummy bind clause in the SPARQL statement
  sparql_stmt := 'SELECT ?c WHERE { 
                  BIND("" as ?s)
                  ?s :parentOf ?c }';
  -- Get the SQL translation for SPARQL statement
  sql_stmt := sem_apis.sparql_to_sql(
                sparql_stmt,
                sem_models('family'),
                SEM_Rulebases('RDFS','family_rb'),
                SEM_ALIASES(SEM_ALIAS('','http://www.example.org/family/')),
                null,' USE_BIND_VAR=PLSQL PLUS_RDFT=VC ');

  -- execute with <http://www.example.org/family/Martha>
  term := '<http://www.example.org/family/Martha>';
  vid := sem_apis.res2vid('MDSYS.RDF_VALUE$',term);

  dbms_output.put_line(chr(10)||'?s='||term);
  open cur for 'select c$rdfterm from('|| sql_stmt || ')' using vid,term;
  loop
    fetch cur into c_val;
    exit when cur%NOTFOUND;
    dbms_output.put_line('|-->?c='||c_val);
  end loop;
  close cur;

  -- execute with <http://www.example.org/family/Sammy>
  term := '<http://www.example.org/family/Sammy>';
  vid := sem_apis.res2vid('MDSYS.RDF_VALUE$',term);

  dbms_output.put_line(chr(10)||'?s='||term);
  open cur for 'select c$rdfterm from('|| sql_stmt || ')' using vid,term;
  loop
    fetch cur into c_val;
    exit when cur%NOTFOUND;
    dbms_output.put_line('|-->?c='||c_val);
  end loop;
  close cur;

END;
/

次に示す例では、Javaから、SEM_APIS.SPARQL_TO_SQLに対するバインド変数が使用されています。この例では、ヒントUSE_BIND_VAR=JDBCが使用されています。

public static void sparqlToSqlTest() {

    try {
        // Get connection
        Connection conn=DriverManager.getConnection( 
                "jdbc:oracle:thin:@localhost:1521:orcl","testuser","testuser");          

        String sparqlStmt =
            "SELECT ?c WHERE {  \n" +
            "  BIND(\"\" as ?s) \n" +
            "  ?s :parentOf ?c      \n" +
            "}";

        // Get SQL translation of SPARQL statement
        // through sem_apis.sparql_to_sql
        OracleCallableStatement ocs = (OracleCallableStatement)conn.prepareCall(
            "begin" +
            "  ? := " +
            "    sem_apis.sparql_to_sql('" +
            "      "+sparqlStmt+"'," +
            "      sem_models('family')," +
            "      SEM_Rulebases('RDFS','family_rb')," +
            "      SEM_ALIASES(SEM_ALIAS('','http://www.example.org/family/')),null," +
            "  ' USE_BIND_VAR=JDBC PLUS_RDFT=VC " +
            " ',null,null);" +
            "end;");          
        ocs.registerOutParameter(1,Types.VARCHAR);
        ocs.execute();
        String sqlStmt = ocs.getString(1);
        ocs.close();

        // Setup statement to lookup value ids
        OracleCallableStatement ocsVid = (OracleCallableStatement)conn.prepareCall(
            "begin" +
            "  ? := sem_apis.res2vid(?,?);" +
            "end;");          

        // Execute SQL setting values for a bind variable
        PreparedStatement stmt=conn.prepareStatement(sqlStmt);

        // lookup value id for first value
        long valueId = 0;
        String term = "<http://www.example.org/family/Martha>";
        ocsVid.registerOutParameter(1,Types.NUMERIC);
        ocsVid.setString(2,"MDSYS.RDF_VALUE$");
        ocsVid.setString(3,term);
        ocsVid.execute();
        valueId = ocsVid.getLong(1);

        stmt.setLong(1, valueId);
        stmt.setString(2, term);
        ResultSet rs=stmt.executeQuery();

        // Print results
        System.out.println("\n?s="+term);
        while(rs.next()) {
            System.out.println("|-->?c=" + rs.getString("c$rdfterm"));
        }
        rs.close();

        // execute the same query for a different URI
        // lookup value id for next value
        valueId = 0;
        term = "<http://www.example.org/family/Sammy>";
        ocsVid.registerOutParameter(1,Types.NUMERIC);
        ocsVid.setString(2,"MDSYS.RDF_VALUE$");
        ocsVid.setString(3,term);
        ocsVid.execute();
        valueId = ocsVid.getLong(1);

        stmt.setLong(1, valueId);
        stmt.setString(2, term);
        rs=stmt.executeQuery();

        // Print results
        System.out.println("\n?s="+term);
        while(rs.next()) {
            System.out.println("|-->?c=" + rs.getString("c$rdfterm"));
        }
        rs.close();

        stmt.close();
        ocsVid.close();
        conn.close(); 

    } catch (SQLException e) {
        e.printStackTrace();
    }
}

1.7.2 SEM_MATCHとSEM_APIS.SPARQL_TO_SQLの比較

SEM_APIS.SPARQL_TO_SQL関数では、書き換え可能な表関数インタフェースを使用していることに起因するSEM_MATCH表関数に固有の制限が回避されています。具体的には、SEM_APIS.SPARQL_TO_SQLでは次のようなことが可能です。

  • 4000バイト(LONG VARCHARに対応している場合32Kバイト)を超えるSPARQL問合せ文字列の使用。

  • SEM_APIS.SPARQL_TO_SQLから返されたプレーンSQLの、読取り専用データベースに対する実行。

  • SEM_APIS.SPARQL_TO_SQLから返されたプレーンSQLの、PL/SQLおよびJDBCのバインド変数への対応。

ただし、SEM_MATCHには、SEM_APIS.SPARQL_TO_SQLにはない特有の機能があります。

  • 射影の最適化への対応。SEM_MATCHの呼び出しで、射影された変数のVAR$RDFVID列のみが選択されている場合に、この変数に対するRDF_VALUE$の結合が回避されます

  • 開始、フェッチ、クローズを行うプロシージャ型表関数の実行が必要な拡張機能への対応(SPARQL SERVICEのSERVICE_JPDWN=TおよびOVERLOADED_NL=Tオプション)。

  • SQL*Plusのようなツールを利用して対話型で問合せを実行する機能。

1.8 セマンティク・データのロードおよびエクスポート

セマンティク・データをデータベース内のモデルにロードすること、およびデータベースからステージング表へえ久ポートすることができます。

セマンティク・データをモデルにロードするには、次の1つ以上のオプションを使用します。

  • RDFトリプル(およびオプションで名前付きグラフ)の3つの構成要素(主語、述語、目的語)を含む行を持つステージング表からセマンティク・データ・ストアにデータをバルク・ロードまたは追加します。詳細は、「ステージング表を使用したセマンティク・データのバルク・ロード」を参照してください。

    このオプションは、大量のデータをロードする場合の最も高速な方法ですが、4000バイトを超える目的語の値を含むトリプルは処理できません。

  • バッチ・ロード: Javaクライアント・インタフェースを使用してN-Triple形式のファイルのデータをセマンティク・データ・ストアにロードまたは追加します(「Java APIを使用したN-Triple形式のセマンティク・データのバッチ・ロード」を参照)。

    このオプションは、バルク・ロードより低速ですが、4000バイトを超える目的語の値を含むトリプルも処理できます。ただし、このオプションでは名前付きグラフは処理されません。

  • SDO_RDF_TRIPLE_SコンストラクタをコールするSQL INSERT文を使用してアプリケーション表にロードし、対応するRDFトリプル(状況によりグラフ名も含む)のセマンティク・データ・ストアに挿入します(「INSERT文を使用したセマンティク・データのロード」を参照)。

    このオプションは、小規模なデータをロードする場合に便利です。

セマンティク・データをエクスポートする、言い換えると、セマンティク・データをステージング表に格納できるN-Triple形式またはN-Quad形式でOracle Databaseから取り出すには、「セマンティク・データのエクスポート」で説明されているSQL問合せを使用します。

注意:

Oracle Databaseリリース12.1では、「Oracle Data Pumpを使用したセマンティク・ネットワークのエクスポートまたはインポート」の説明にあるとおり、Oracle Data Pumpユーティリティの全てのデータベース・エクスポートおよびインポートの機能を使用して、セマンティク・ネットワークのエクスポートとインポートを行うことができます。

1.8.1 ステージング表を使用したセマンティク・データのバルク・ロード

ステージング表を使用して、セマンティク・データ(およびオプションでセマンティク・データ以外の関連データ)をバルク・ロードできます。SEM_APIS.LOAD_INTO_STAGING_TABLEプロシージャ(「SEM_APISパッケージ・サブプログラム」を参照)をコールしてデータをロードします(ロード操作中に構文の正確性をチェックできます)。その後、SEM_APIS.BULK_LOAD_FROM_STAGING_TABLEプロシージャをコールして、データをステージング表からセマンティク・ストアにロードできます。(データがステージング表へのロード操作中に解析されていない場合は、SEM_APIS.BULK_LOAD_FROM_STAGING_TABLEプロシージャをコールするときにflagsパラメータにPARSEキーワードを指定する必要があります。)

次の例では、すべての必須列とそれらの列の必須名(およびロードする1つ以上のRDFトリプルにグラフ名が含まれる場合は、含まれる必要のあるオプションのRDF$STC_graph列)を含むステージング表の書式を示します。

CREATE TABLE stage_table (
                     RDF$STC_sub varchar2(4000) not null,
                     RDF$STC_pred varchar2(4000) not null,
                     RDF$STC_obj varchar2(4000) not null,
                     RDF$STC_graph varchar2(4000)
);

非セマンティク・データもロードする場合は、CREATE TABLE文に非セマンティク・データ用の追加列を指定します。非セマンティク列の名前の形式は、必須列の名前と異なる必要があります。次の例では、非セマンティク属性用の2つの追加列(SOURCEおよびID)を含むステージング表を作成します。

CREATE TABLE stage_table_with_extra_cols (
                     source VARCHAR2(4000),
                     id NUMBER,
                     RDF$STC_sub varchar2(4000) not null,
                     RDF$STC_pred varchar2(4000) not null,
                     RDF$STC_obj varchar2(4000) not null,
                     RDF$STC_graph varchar2(4000)
);

注意:

いずれの形式のCREATE TABLE文でも、表を圧縮するためにCOMPRESS句を追加できます。このオプションにより、必要なディスク領域が減少し、バルク・ロードのパフォーマンスが向上する可能性があります。

起動側とMDSYSユーザーは、両方ともステージング表に対するSELECT権限と、アプリケーション表に対するINSERT権限を持っている必要があります。

次の項も参照してください。

1.8.1.1 ステージング表のロード

セマンティク・ストアへのロードの準備として、複数の方法でセマンティク・データをステージング表にロードできます。一般的な方法は次のとおりです。

1.8.1.1.1 SQL*Loaderを使用したステージング表へのN-Triple形式のデータのロード

SQL*Loaderユーティリティを使用して、セマンティク・データを解析し、ステージング表にロードします。Oracle Database Examplesメディアからデモ・ファイルをインストールしている場合(『Oracle Database Examplesインストレーション・ガイド』を参照)、サンプルの制御ファイル$ORACLE_HOME/md/demo/network/rdf_demos/bulkload.ctlを使用できます。入力データがN-Triple形式の場合、このファイルを変更して使用できます。

4000バイトを超える目的語はロードできません。サンプルのSQL*Loader制御ファイルを使用する場合、このような長い値を含むトリプル(行)は、自動的に拒否され、SQL*Loaderの不良ファイルに格納されます。ただし、これらの拒否された行は、SQL INSERT文を使用してアプリケーション表に挿入することによってロードできます(「INSERT文を使用したセマンティク・データのロード」を参照)。

1.8.1.1.2 外部表を使用したステージング表へのN-Quad形式のデータのロード

次の方法によって、Oracle外部表を使用してステージング表にN-Quad形式のデータ(4つの構成要素を持つ拡張トリプル)をロードできます。

  1. SEM_APIS.CREATE_SOURCE_EXTERNAL_TABLEプロシージャをコールして外部表を作成し、SQL STATEMENT ALTER TABLEを使用して、関連する1つ以上の入力ファイル名を含めるように外部表を変更します。1つ以上の入力ファイルを含むフォルダに関連付けられたディレクトリ・オブジェクトに対するREAD権限とWRITE権限を持っている必要があります。
  2. 外部表を作成したら、MDSYSユーザーに、表に対するSELECT権限とINSERT権限を付与します。
  3. SEM_APIS.LOAD_INTO_STAGING_TABLEプロシージャをコールしてステージング表に移入します。
  4. ロードが終了したら、COMMIT文を発行してトランザクションを完了します。

例1-91 外部表を使用してステージング表をロードする方法

-- Create a source external table (note: table names are case sensitive)
BEGIN
  sem_apis.create_source_external_table(
    source_table    => 'stage_table_source'
   ,def_directory   => 'DATA_DIR'
   ,bad_file        => 'CLOBrows.bad'
   );
END;
/
grant SELECT on "stage_table_source" to MDSYS;
 
-- Use ALTER TABLE to target the appropriate file(s)
alter table "stage_table_source" location ('demo_datafile.nt');
 
-- Load the staging table (note: table names are case sensitive)
BEGIN
  sem_apis.load_into_staging_table(
    staging_table => 'STAGE_TABLE'
   ,source_table  => 'stage_table_source'
   ,input_format  => 'N-QUAD');
END;
/

オブジェクトとグラフURI (結合)の長さが4000バイトを超える行は、拒否されて不良ファイルに格納されます。ただし、これらの拒否された行は、SQL INSERT文を使用してアプリケーション表に挿入することによってロードできます(「INSERT文を使用したセマンティク・データのロード」を参照)。

例1-91は、外部表を使用してステージング表をロードする方法を示します。

1.8.1.2 バルク・ロード中のイベント・トレースの記録

起動側のスキーマに表RDF$ET_TABが存在し、この表に対するINSERT権限とUPDATE権限がMDSYSユーザーに付与されている場合、SEM_APIS.BULK_LOAD_FROM_STAGING_TABLEプロシージャ実行中に実行されるタスクの一部に対するイベント・トレースが表に追加されます。バルク・ロードの問題を報告する必要がある場合は、この表の内容が役に立ちます。RDF$ET_TAB表は、次のようにして作成してください。

CREATE TABLE RDF$ET_TAB (
  proc_sid VARCHAR2(30), 
  proc_sig VARCHAR2(200),
  event_name varchar2(200),
  start_time timestamp,
  end_time timestamp,
  start_comment varchar2(1000) DEFAULT NULL,
  end_comment varchar2(1000) DEFAULT NULL
);
GRANT INSERT, UPDATE on RDF$ET_TAB to MDSYS;

1.8.2 Java APIを使用したN-Triple形式のセマンティク・データのバッチ・ロード

注意:

この項で説明するJavaクラスoracle.spatial.rdf.client.BatchLoaderは非推奨になり、N-Quadデータのロードをサポートしていません。

かわりに、「RDF Semantic Graph Support for Apache Jenaを使用したバルク・ロード」で説明する、RDF Semantic Graph Support for Apache Jenaのバルク・ロード機能の使用をお薦めします。

N-Triple形式のセマンティク・データのバッチ(バルク)・ロード操作を実行するには、<ORACLE_HOME>/md/jlib/sdordf.jarにパッケージされているJavaクラス oracle.spatial.rdf.client.BatchLoaderを使用します。バッチ・ロード操作を実行する前に、次のことを確認してください。

  • セマンティク・データがN-Triple形式であること。(RDF/XMLからN-Triple形式への変換に使用できるツールがいくつか存在します。Oracle Technology Networkを参照するか、RDF/XMLからN-Tripleへの変換に関する情報をWebで検索してください。)

  • Oracle Databaseリリース11以上が、Oracle Spatial and Graphとともにインストールされており、パーティショニング機能が有効であること。

  • セマンティク・テクノロジ・ネットワーク、アプリケーション表、および対応するセマンティク・モデルがデータベースに作成されていること。

  • CLASSPATH定義にojdbc6.jarが含まれていること。

  • JDKバージョン1.5以上を使用していること。(<ORACLE_HOME>/jdk/binにパッケージされたJavaバージョンを使用できます。)

oracle.spatial.rdf.client.BatchLoaderクラスを実行するには、単一のコマンドラインで次の一般的な形式のコマンドを使用します(サンプルのデータベース接続情報は、実際の接続情報で置き換えてください)。

  • Linuxシステム:

    java -Ddb.user=scott -Ddb.password=password -Ddb.host=127.0.0.1 -Ddb.port=1522 -Ddb.sid=orcl -classpath ${ORACLE_HOME}/md/jlib/sdordf.jar:${ORACLE_HOME}/jdbc/lib/ojdbc6.jar oracle.spatial.rdf.client.BatchLoader <N-TripleFile> <tablename> <tablespaceName> <modelName>
    
  • Windowsシステム:

    java -Ddb.user=scott -Ddb.password=password -Ddb.host=127.0.0.1 -Ddb.port=1522 -Ddb.sid=orcl -classpath %ORACLE_HOME%\md\jlib\sdordf.jar;%ORACLE_HOME%\jdbc\lib\ojdbc6.jar oracle.spatial.rdf.client.BatchLoader <N-TripleFile> <tablename> <tablespaceName> <modelName>
    

-Ddb.user-Ddb.passwordの値は、モデル<modelName>の所有者またはDBAユーザーに一致している必要があります。

デフォルトでは、BatchLoaderは、少なくともNUMBER型のIDおよびSDO_RDF_TRIPLE_S型のTRIPLEをそれぞれ名前に持つ2列がユーザーのアプリケーション表にあることを前提としています。ただし、デフォルトの名前をJVMプロパティの-DidColumn=<idColumnName>および-DtripleColumn=<tripleColumnName>をオーバーライドして変更できます。ID列は必要ありません。BatchLoaderが順序風の識別子を各トリプルのID列のかわりに生成しないように、追加のJVMプロパティで-DjustTriple=trueと指定します。

アプリケーション表が空ではなく、アペンド・モードでバッチ・ロードを実行する場合には、追加のJVMプロパティで-Dappend=trueと指定します。さらにアペンド・モードで、ユーザーのアプリケーション表のID列に異なる開始値を指定する場合には、コマンドラインからJVMプロパティ-DstartID=<startingIntegerValue>を追加します。デフォルトでは、ID列は1から始まり、新しいトリプルがアプリケーション表に挿入されると1つずつ増えるようになっています。

<N-TripleFile>の先頭のn個のトリプルをスキップするには、コマンドラインにJVMプロパティ-Dskip=<numberOfTriplesSkipped>を追加します。

デフォルトとは異なるキャラクタ・セットでN-Tripleファイルをロードするには、JVMプロパティ-Dcharset=<charsetName>を指定します。たとえば、-Dcharset="UTF-8"と指定すると、UTF-8エンコーディングとして認識されます。ただし、UTF-8文字をN-Tripleファイルに適切に格納するには、AL32UTF8などの対応する汎用キャラクタ・セットを使用するようOracle Databaseを構成する必要があります。

BatchLoaderクラスでは、圧縮形式のN-Tripleファイルのロードがサポートされます。<N-TripleFile>の拡張子が.zipや.jarである場合、そのファイルの解凍とロードが同時に実行されます。

1.8.3 INSERT文を使用したセマンティク・データのロード

INSERT文を使用してセマンティク・データをロードする場合、URIは< >(山カッコ)で、空白ノードは_:(アンダースコアとコロン)で、リテラルは" "(引用符)で囲む必要があります。URIまたは空白ノードに空白文字を使用することはできません。データを挿入するには、SDO_RDF_TRIPLE_Sコンストラクタを使用します(「トリプルを挿入するためのコンストラクタ」を参照)。アプリケーション表に対するINSERT権限を持っている必要があります。

注意:

URIが< >で、リテラルが" "で囲まれていなくても、文はそのまま処理されます。ただし、VALUE_TYPE値の判定に余分な処理が必要とされるため、文によるロードに時間がかかります。

次の例には、URI、空白ノード、リテラル、言語タグ付きのリテラルおよび型付きリテラルを使用した文が含まれます。

INSERT INTO nsu_data VALUES (SDO_RDF_TRIPLE_S('nsu', '<http://nature.example.com/nsu/rss.rdf>',
  '<http://purl.org/rss/1.0/title>', '"Nature''s Science Update"'));
INSERT INTO nsu_data VALUES (SDO_RDF_TRIPLE_S('nsu', '_:BNSEQN1001A',
  '<http://www.w3.org/1999/02/22-rdf-syntax-ns#type>', 
  '<http://www.w3.org/1999/02/22-rdf-syntax-ns#Seq>'));
INSERT INTO nsu_data VALUES (SDO_RDF_TRIPLE_S('nsu',
  '<http://nature.example.com/cgi-taf/dynapage.taf?file=/nature/journal/v428/n6978/index.html>',
  '<http://purl.org/dc/elements/1.1/language>', '"English"@en-GB'));
INSERT INTO nature VALUES (SDO_RDF_TRIPLE_S('nsu', '<http://dx.doi.org/10.1038/428004b>',
  '<http://purl.org/dc/elements/1.1/date>', '"2004-03-04"^^xsd:date'));

セマンティクXMLデータをINSERT文に変換するには、サンプルのrss2insert.xsl XSLTファイルを編集してセマンティク・データXMLファイルのすべての機能を変換します。空白ノード・コンストラクタは、空白ノードを含む文を挿入する場合に使用します。XSLTを編集したら、Xalan XSLTプロセッサ(http://xml.apache.org/xalan-j/)をダウンロードし、そのインストール指示に従います。編集したバージョンのrss2insert.xslファイルを使用してセマンティク・データXMLファイルをINSERT文に変換するには、次の形式のコマンドを使用します。

java org.apache.xalan.xslt.Process –in input.rdf -xsl rss2insert.xsl –out output.nt
1.8.3.1 INSERT文を使用した名前付きグラフへのデータのロード

INSERT文を使用してnull以外のグラフ名を含むRDFトリプルをロードするには、次の例に示すように、モデル名とコロン(:)区切り文字の後に、グラフ名を山カッコ(< >)で囲んで追加する必要があります。

INSERT INTO articles_rdf_data VALUES ( 
  SDO_RDF_TRIPLE_S ('articles:<http://examples.com/ns#Graph1>',
    '<http://nature.example.com/Article101>',
    '<http://purl.org/dc/elements/1.1/creator>',
    '"John Smith"'));

1.8.4 セマンティク・データのエクスポート

この項には、セマンティク・データのエクスポート(つまり、セマンティク・データをステージング表に格納できるN-Triple形式またはN-Quad形式でOracle Databaseから取り出す)に関連する、次のトピックがあります。

1.8.4.1 アプリケーション表からのセマンティク・データの取得

例1-92のように、SDO_RDF_TRIPLE_Sメンバー関数を使用して、アプリケーション表からセマンティク・データを取得することができます(この例では、読みやすいように出力をフォーマットしなおしてあります)。

例1-92 アプリケーション表からのセマンティク・データの取得

--
-- Retrieves model-graph, subject, predicate, and object
--
SQL> SELECT a.triple.GET_MODEL() AS model_graph, a.triple.GET_SUBJECT() AS sub, a.triple.GET_PROPERTY() pred, a.triple.GET_OBJECT() obj FROM articles_rdf_data a;

MODEL_GRAPH
--------------------------------------------------------------------------------
SUB
--------------------------------------------------------------------------------
PRED
--------------------------------------------------------------------------------
OBJ
--------------------------------------------------------------------------------
ARTICLES
<http://nature.example.com/Article1>
<http://purl.org/dc/elements/1.1/title>
"All about XYZ"


ARTICLES
<http://nature.example.com/Article1>
<http://purl.org/dc/elements/1.1/creator>
"Jane Smith"


ARTICLES
<http://nature.example.com/Article1>
<http://purl.org/dc/terms/references>
<http://nature.example.com/Article2>


ARTICLES
<http://nature.example.com/Article1>
<http://purl.org/dc/terms/references>
<http://nature.example.com/Article3>


ARTICLES
<http://nature.example.com/Article2>
<http://purl.org/dc/elements/1.1/title>
"A review of ABC"


ARTICLES
<http://nature.example.com/Article2>
<http://purl.org/dc/elements/1.1/creator>
"Joe Bloggs"


ARTICLES
<http://nature.example.com/Article2>
<http://purl.org/dc/terms/references>
<http://nature.example.com/Article3>


7 rows selected.
1.8.4.2 RDFモデルからのセマンティク・データの取得

例1-93に示すように、SEM_MATCH表関数(「SEM_MATCH表関数を使用したセマンティク・データの問合せ」を参照)を使用して、セマンティク・データをRDFモデルから取得できます。

例1-93 RDFモデルからのセマンティク・データの取得

--
-- Retrieves graph, subject, predicate, and object
--
SQL> select to_char(g$rdfterm) graph, to_char(x$rdfterm) sub, to_char(p$rdfterm) pred, y$rdfterm obj from table(sem_match('Select ?g ?x ?p ?y FROM NAMED <http://examples.com/ns#Graph1> {GRAPH ?g {?x ?p ?y}}',sem_models('articles'),null,null,null,null,' GRAPH_MATCH_UNNAMED=T PLUS_RDFT=T '));
 
GRAPH
------------------------------------------------------------
SUB
------------------------------------------------------------
PRED
------------------------------------------------------------
OBJ
---------------------------------------------------------------------------
<http://examples.com/ns#Graph1>
_:m99g3C687474703A2F2F6578616D706C65732E636F6D2F6E73234772617068313Egmb2
<http://purl.org/dc/elements/1.1/creator>
_:m99g3C687474703A2F2F6578616D706C65732E636F6D2F6E73234772617068313Egmb1
 
<http://examples.com/ns#Graph1>
<http://nature.example.com/Article102>
<http://purl.org/dc/elements/1.1/creator>
_:m99g3C687474703A2F2F6578616D706C65732E636F6D2F6E73234772617068313Egmb1
 
<http://examples.com/ns#Graph1>
<http://nature.example.com/Article101>
<http://purl.org/dc/elements/1.1/creator>
"John Smith"
 
<http://nature.example.com/Article1>
<http://purl.org/dc/elements/1.1/creator>
"Jane Smith"
1.8.4.3 取得した空白ノード識別子からのモデルおよびグラフ情報の削除

セマンティク・データの取得中に取得された空白ノード識別子は、例1-94のコード抜粋に示す変換を使用してモデルとグラフ情報を削除するようにトリミング可能であり、それぞれVARCHAR2 (主語コンポーネントなど)およびCLOB (目的語コンポーネントなど)データに適用できます。

例1-95に、「RDFモデルからのセマンティク・データの取得」に説明されているセマンティク・データ取得問合せを使用して、それぞれsub列とobj列に対して例1-94の2つの変換を使用した後に取得された結果を示します。

例1-94 アプリケーション表からのセマンティク・データの取得

--
-- Transformation on column "sub VARCHAR2" 
-- holding blank node identifier values
--
Select (case substr(sub,1,2) when '_:' then '_:' || substr(sub,instr(sub,'m',1,2)+1) else sub end) from …
--
-- Transformation on column "obj CLOB" 
-- holding blank node identifier values
--
Select (case dbms_lob.substr(obj,2,1) when '_:' then to_clob('_:' || substr(obj,instr(obj,'m',1,2)+1)) else obj end) from …

例1-95 例1-94の変換の適用による結果

--
-- Results obtained by applying transformations on the sub and pred cols
-- 
SQL> select (case substr(sub,1,2) when '_:' then '_:' || substr(sub,instr(sub,'m',1,2)+1) else sub end) sub, pred, (case dbms_lob.substr(obj,2,1) when '_:' then to_clob('_:' || substr(obj,instr(obj,'m',1,2)+1)) else obj end) obj from (select to_char(g$rdfterm) graph, to_char(x$rdfterm) sub, to_char(p$rdfterm) pred, y$rdfterm obj from table(sem_match('Select ?g ?x ?p ?y FROM NAMED <http://examples.com/ns#Graph1> {GRAPH ?g {?x ?p ?y}}',sem_models('articles'),null,null,null,null,' GRAPH_MATCH_UNNAMED=T PLUS_RDFT=T ')));
 
SUB
------------------------------------------------------------
PRED
------------------------------------------------------------
OBJ
---------------------------------------------------------------------------
_:b2
<http://purl.org/dc/elements/1.1/creator>
_:b1
 
<http://nature.example.com/Article102>
<http://purl.org/dc/elements/1.1/creator>
_:b1

1.8.5 Oracle Data Pumpを使用したセマンティク・ネットワークのエクスポートまたはインポート

Oracle Databaseリリース12.1では、Oracle Data Pumpユーティリティの全データベース・エクスポートおよびインポートの機能を使用して、セマンティク・ネットワークをエクスポートおよびインポートできます。ネットワークは、全データベース・エクスポートまたはインポートの一部として移動し、データベース全体がOracleのダンプ・ファイル(.dmp)で表現されます。

データ・ポンプを使用したセマンティク・ネットワークのエクスポートまたはインポートには、次の使用上の注意があります。

  • インポートのターゲット・データベースには、RDFセマンティク・グラフのソフトウェアがインストールされ、既存のセマンティク・ネットワークが存在していないことが必要です。

  • ファイングレイン・アクセス制御を使用するセマンティク・ネットワーク(トリプルレベルまたはリソースレベルのOLSまたはVPD)は、エクスポートまたはインポートできません。

  • SEM_CONTAINS (MDSYS.SEMCONTEXT索引タイプ)のセマンティク・ドキュメント索引と、SEM_RELATED (MDSYS.SEM_INDEXTYPE索引タイプ)のセマンティク索引は、エクスポートの前に削除し、インポート後に再作成する必要があります。

  • エクスポートおよびインポート中は、セマンティク・ネットワーク・オブジェクトに対するデフォルトの(オブジェクトの作成直後に存在する)権限のみが保持されます。たとえばユーザーAがセマンティク・モデルMを作成し、MDSYS.RDFM_Mに対するSELECTをユーザーBに付与した場合、インポート後に残るのは、MDSYS.RDFM_Mに対するユーザーAのSELECT権限のみです。インポート後、ユーザーBには、MDSYS.RDFM_Mに対するSELECT権限がありません。かわりにユーザーBのSELECT権限が再度付与されます。

  • セマンティク・ネットワーク・データのエクスポートまたはインポート時には、データ・ポンプのコマンドライン・オプションtransform=oid:nを使用する必要があります。たとえば、次の形式のコマンドを使用します。

    impdp system/<password-for-system> directory=dpump_dir dumpfile=rdf.dmp full=YES version=12 transform=oid:n
    

データ・ポンプの使用方法に関する情報および例については、『Oracle Databaseユーティリティ』を参照してください。

1.8.6 未使用値のパージ

時間の経過に伴うトリプルの削除によって、RDF_VALUE$表の値のサブセットは、現在セマンティク・ネットワークに含まれるどのRDFトリプルまたはルールでも使用されなくなる可能性があります。このような使用されていない値の数が多くなり、RDF_VALUE$表の大部分を占めるようになった場合、SEM_APIS.PURGE_UNUSED_VALUESサブプログラムを使用して未使用値をパージできます。

パージする前に、MDSYSに、すべてのRDFモデルのアプリケーション表に対するSELECT権限を付与する必要があります。これを行うには、GRANTコマンドを直接使用するか、SEM_APIS.PRIVILEGE_ON_APP_TABLESサブプログラムを使用します。

パージ操作中に実行されたタスクのイベント・トレースは、RDF$ET_TAB表が起動側のスキーマに存在する場合、そこに記録できます(「バルク・ロード中のイベント・トレースの記録」を参照)。

次の例では、RDF_VALUE$表から未使用値をパージします。この例では、名前付きグラフまたはCLOBを考慮していません。また、「例: 雑誌記事の情報」の例のデータがロードされていることを前提としています。

例1-96 未使用値のパージ

-- Purging unused values
set numwidth 20

-- Create view to show the values actually used in the RDF model
CREATE VIEW values_used_in_model (value_id) as
  SELECT a.triple.rdf_s_id FROM articles_rdf_data a UNION
  SELECT a.triple.rdf_p_id FROM articles_rdf_data a UNION
  SELECT a.triple.rdf_c_id FROM articles_rdf_data a UNION
  SELECT a.triple.rdf_o_id FROM articles_rdf_data a;
 
View created.

-- Create views to show triples in the model
CREATE VIEW triples_in_app_table as
  SELECT a.triple.GET_SUBJECT() AS s, a.triple.GET_PROPERTY() AS p, a.triple.GET_OBJ_VALUE() AS o
    FROM articles_rdf_data a;
 
View created.

CREATE VIEW triples_in_rdf_model as
  SELECT s, p, o FROM TABLE ( SEM_MATCH('{?s ?p ?o}', SEM_MODELS('articles'), null, null, null ));
 
View created.

--
-- Content before deletion
--

-- Values in mdsys.RDF_VALUE$
CREATE TABLE values_before_deletion as select value_id from mdsys.rdf_value$;
 
Table created.

-- Values used in the RDF model
CREATE TABLE used_values_before_deletion as
  SELECT * FROM values_used_in_model;
 
Table created.

-- Content of RDF model
CREATE TABLE atab_triples_before_deletion
  as select * from triples_in_app_table;
 
Table created.

CREATE TABLE model_triples_before_deletion
  as select * from triples_in_rdf_model;
 
Table created.

-- Delete some triples so that some of the values become unused
DELETE FROM articles_rdf_data a
   WHERE a.triple.GET_PROPERTY() = '<http://purl.org/dc/elements/1.1/title>'
     OR a.triple.GET_SUBJECT() = '<http://nature.example.com/Article1>';
 
5 rows deleted.

-- Content of RDF model after deletion
CREATE TABLE atab_triples_after_deletion
  as select * from triples_in_app_table;
 
Table created.

CREATE TABLE model_triples_after_deletion
  as select * from triples_in_rdf_model;
 
Table created.

-- Values that became unused in the RDF model
SELECT * from used_values_before_deletion
  MINUS
  SELECT * FROM values_used_in_model;
 
VALUE_ID
--------------------
 1399113999628774496
 4597469165946334122
 6345024408674005890
 7299961478807817799
 7995347759607176041

-- RDF_VALUE$ content, however, is unchanged
SELECT value_id from values_before_deletion
  MINUS
  select value_id from mdsys.rdf_value$;
 
no rows selected

-- Now purge the values from RDF_VALUE$ (requires that MDSYS has
-- SELECT privilege on *all* the app tables in the semantic network)
EXECUTE sem_apis.privilege_on_app_tables;
 
PL/SQL procedure successfully completed.
 
EXECUTE sem_apis.purge_unused_values;
 
PL/SQL procedure successfully completed.

-- RDF_VALUE$ content is NOW changed due to the purge of unused values
SELECT value_id from values_before_deletion
  MINUS
  select value_id from mdsys.rdf_value$;
 
VALUE_ID
--------------------
 1399113999628774496
 4597469165946334122
 6345024408674005890
 7299961478807817799
 7995347759607176041

-- Content of RDF model after purge
CREATE TABLE atab_triples_after_purge
  as select * from triples_in_app_table;
 
Table created.

CREATE TABLE model_triples_after_purge
  as select * from triples_in_rdf_model;
 
Table created.

-- Compare triples present before purging of values and after purging
SELECT * from atab_triples_after_deletion
  MINUS
  SELECT * FROM atab_triples_after_purge;
 
no rows selected

SELECT * from model_triples_after_deletion
  MINUS
  SELECT * FROM model_triples_after_purge;
 
no rows selected

1.9 セマンティク・ネットワーク索引の使用

セマンティク・ネットワーク索引は、一意でないBツリー索引です(セマンティク・ネットワーク索引を追加、変更および削除して、セマンティク・ネットワーク内のモデルや伴意とともに使用できます)。

このような索引を使用すると、ネットワーク内のモデルや伴意に対するSEM_MATCH問合せのパフォーマンスを調整できます。任意の索引と同様に、セマンティク・ネットワーク索引によって、問合せワークロードに適合する索引ベースのアクセスが可能になります。これによって、次の例のシナリオのようにパフォーマンスが大幅に向上する可能性があります。

  • グラフ・パターンが'{<John> ?p <Mary>}'の場合は、1つ以上のターゲット・モデルに対して、対応する伴意で(問合せで使用される場合)、便利な'CSP'または'SCP'索引を使用できます。

  • グラフ・パターンが'{?x <talksTo> ?y . ?z ?p ?y}'の場合は、Cを主要なキーとして使用して('C''CPS'など)、関連する1つ以上のモデルおよび伴意に便利なセマンティク・ネットワーク索引を用意できます。

ただし、セマンティク・ネットワーク索引を使用すると、DML、ロードおよび推論操作に必要な時間が増加して、パフォーマンス全体が影響を受ける可能性があります。

セマンティク・ネットワーク索引は、次のサブプログラムを使用して作成および管理できます。

これらのサブプログラムはすべてindex_codeパラメータを持ち、このパラメータには、PCSGMを任意の順序(繰返しなし)で含めることができます。index_code内で使用されたこれらの文字は、ビューSEMM_*およびSEMI_*の列P_VALUE_ID、CANON_END_NODE_ID、START_NODE_ID、G_IDおよびMODEL_IDに対応しています。

SEM_APIS.ADD_SEM_INDEXプロシージャは、セマンティク・ネットワーク索引を作成し、これにより、既存のモデルおよび伴意それぞれに対して、一意でないBツリー索引がUNUSABLEステータスで作成されます。この索引の名前はRDF_LNK_<index_code>_IDXとなり、索引の所有者はMDSYSとなります。この操作は、起動側にDBAロールがある場合にのみ許可されます。次の例では、キー<P_VALUE_ID, START_NODE_ID, CANON_END_NODE_ID, G_ID, MODEL_ID>を使用してPSCGM索引を作成しています。

EXECUTE SEM_APIS.ADD_SEM_INDEX('PSCGM');

セマンティク・ネットワーク索引を作成すると、それぞれ対応する一意ではないBツリー索引がUNUSABLEステータスになります。これは、この検索の使用による長時間の処理や大量のリソース消費、さらにはそれらに伴って発生する索引のメンテナンス操作により望ましくないパフォーマンス・コストが発生する可能性があるからです。SEM_APIS.ALTER_SEM_INDEX_ON_MODELおよびSEM_APIS.ALTER_SEM_INDEX_ON_ENTAILMENTプロシージャをコールしたときにcommandパラメータとして'REBUILD'または'UNUSABLE'を指定することで、所有する特定のモデルや伴意でセマンティク・ネットワーク索引を使用または不使用に設定できます。セマンティク・ネットワーク索引を使用または不使用にして、パフォーマンスに違いが出るか確認できます。たとえば、次の文はPSCGM索引をFAMILYモデルで使用できるように設定します。

EXECUTE SEM_APIS.ALTER_SEM_INDEX_ON_MODEL('FAMILY','PSCGM','REBUILD');

また、次の点にも注意してください。

  • 自分で作成したセマンティク・ネットワーク索引とは無関係に、セマンティク・ネットワークが作成されると自動的に作成される索引の1つに、この項に示したサブプログラムをコールするときにindex_code'PSCGM'と指定することで管理できる索引があります。

  • 新規のモデルまたは新規の伴意を作成すると、セマンティク・ネットワーク索引ごとに一意でない新規のBツリー索引が作成されますが、このようなBツリー索引はいずれも、USABLEステータスになります。

  • (index_code値に'M'を含めることにより)セマンティク・ネットワーク索引キーにMODEL_ID列を含めると、問合せのパフォーマンスが向上することがあります。特に、仮想モデルを使用する場合はこの操作が有効です。

1.9.1 MDSYS.SEM_NETWORK_INDEX_INFOビュー

モデルと伴意のすべてのネットワーク索引に関する情報は、MDSYS.SEM_NETWORK_INDEX_INFOビューに保持されます(表1-17に、このビューの列(部分リスト)を示します(1つの行が1つのネットワーク索引に対応します))。

表1-17 MDSYS.SEM_NETWORK_INDEX_INFOビューの列(部分リスト)

列名 データ型 説明

NAME

VARCHAR2(30)

RDFモデルまたは伴意の名前

TYPE

VARCHAR2(10)

索引が構築されるオブジェクトのタイプ: MODELENTAILMENTまたはNETWORK

ID

NUMBER

モデルまたは伴意のID番号、またはネットワークに対する索引の場合は0 (ゼロ)

INDEX_CODE

VARCHAR2(25)

索引のコード(たとえばPSCGM)

INDEX_NAME

VARCHAR2(30)

索引の名前(たとえば、RDF_LNK_PSCGM_IDX)

LAST_REFRESH

TIMESTAMP(6)WITH TIME ZONE

このコンテンツがリフレッシュされた最終時刻のタイムスタンプ

表1-17に示した列の他に、MDSYS.SEM_NETWORK_INDEX_INFOビューには、ALL_INDEXESおよびALL_IND_PARTITIONSビュー(どちらも『Oracle Databaseリファレンス』を参照)から得られる次の列を含みます。

  • ALL_INDEXESビュー: UNIQUENESS、COMPRESSION、PREFIX_LENGTH

  • ALL_IND_PARTITIONSビュー: STATUS、TABLESPACE_NAME、BLEVEL、LEAF_BLOCKS、NUM_ROWS、DISTINCT_KEYS、AVG_LEAF_BLOCKS_PER_KEY、AVG_DATA_BLOCKS_PER_KEY、CLUSTERING_FACTOR、SAMPLE_SIZE、LAST_ANALYZED

MDSYS.SEM_NETWORK_INDEX_INFOビューの情報は失効している場合があることに注意してください。この情報をリフレッシュするには、SEM_APIS.REFRESH_SEM_NETWORK_INDEX_INFOプロシージャを使用します。

1.10 データ型索引の使用

データ型索引は、セマンティク・ネットワークに格納される型付きリテラルの値の索引です。

この索引を使用すると、特定のタイプのFILTER式を含むSEM_MATCH問合せのパフォーマンスが大幅に向上する場合があります。たとえば、xsd:dateTimeリテラルのデータ型索引によって、フィルタ(?x < "1929-11-16T13:45:00Z"^^xsd:dateTime)の評価の速度が向上する場合があります。索引を作成できるいくつかのデータ型を、表1-18に示します。

表1-18 データ型索引のデータ型

データ型URI Oracle型 索引型

http://www.w3.org/2001/XMLSchema#decimal

NUMBER

一意でないBツリー(xsd:floatxsd:doublexsd:decimal などのすべてのxsd数値型とそのすべてのサブタイプに対応する単一の索引を作成)

http://www.w3.org/2001/XMLSchema#string

VARCHAR2

一意ではないBツリー(xsd:string型付きリテラルとプレーン・リテラルに対して単一の索引を作成します)

http://www.w3.org/2001/XMLSchema#time

TIMESTAMP WITH TIMEZONE

一意でないBツリー

http://www.w3.org/2001/XMLSchema#date

TIMESTAMP WITH TIMEZONE

一意でないBツリー

http://www.w3.org/2001/XMLSchema#dateTime

TIMESTAMP WITH TIMEZONE

一意でないBツリー

http://xmlns.oracle.com/rdf/text

(該当なし)

CTXSYS.CONTEXT

http://xmlns.oracle.com/rdf/geo/WKTLiteral

SDO_GEOMETRY

MDSYS.SPATIAL_INDEX

http://www.opengis.net/geosparql#wktLiteral

SDO_GEOMETRY

MDSYS.SPATIAL_INDEX

http://www.opengis.net/geosparql#gmlLiteral

SDO_GEOMETRY

MDSYS.SPATIAL_INDEX

http://xmlns.oracle.com/rdf/like

VARCHAR2

一意でないBツリー

データ型索引が適切かどうかは、問合せのワークロードに応じて異なります。xsdデータ型でのデータ型索引は、変数を定数値と比較するフィルタに使用可能であり、特に、非常に選択的なフィルタ条件を持つ選択的でないグラフ・パターンが問合せに含まれる場合に役立ちます。適切なデータ型索引は、空間フィルタまたはテキスト・フィルタを使用する問合せに必要です。

データ型索引によって問合せパフォーマンスは向上しますが、徐々に増加する索引のメンテナンスによって、セマンティク・ネットワークに対するDMLおよびバルク・ロード操作のパフォーマンスが低下する可能性があります。バルク・ロード操作では、通常、データ型索引を削除し、バルク・ロードを実行してからデータ型索引を再作成する方が高速です。

以下のプロシージャを使ってデータ型索引を追加、変更、削除することができます。これらのプロシージャの説明は、「SEM_APISパッケージのサブプログラム」に記載されています。

既存のデータ型索引に関する情報は、MDSYS.SEM_DTYPE_INDEX_INFOビューに保持されます。表1-19に、このビューの列を示します(1つの行が1つのルール索引に対応します)。

表1-19 MDSYS.SEM_DTYPE_INDEX_INFOビューの列

列名 データ型 説明

DATATYPE

VARCHAR2(51)

データ型URI

INDEX_NAME

VARCHAR2(30)

索引の名前

STATUS

VARCHAR2(8)

索引のステータス: USABLEまたはUNUSABLE

TABLESPACE_NAME

VARCHAR2(30)

索引の表領域

FUNCIDX_STATUS

VARCHAR2(8)

関数ベース索引の状態。取り得る値は、NULLENABLEDまたはDISABLEDです。

例1-97に示すとおり、誕生日が1929年11月16日より前のすべての祖父を見つける問合せの評価中にデータ型索引を使用するように、HINT0ヒントを使用できます。

例1-97 HINT0を使用してデータ型索引が使用されるようにする方法

SELECT x, y
  FROM TABLE(SEM_MATCH(
    '{?x :grandParentOf ?y . ?x rdf:type :Male . ?x :birthDate ?bd
       FILTER (?bd <= "1929-11-15T23:59:59Z"^^xsd:dateTime) }',
    SEM_Models('family'),
    SEM_Rulebases('RDFS','family_rb'), 
    SEM_ALIASES(SEM_ALIAS('','http://www.example.org/family/')),
    null, null, 
    'HINT0={ LEADING(?bd) INDEX(?bd rdf_v$dateTime_idx) } 
             FAST_DATE_FILTER=T' ));

1.11 セマンティク・モデルおよびセマンティク・ネットワークの統計の管理

統計は、Oracle Databaseに格納されているセマンティク・データに対するSPARQL問合せおよびOWL推論のパフォーマンスに重要な意味を持ちます。

Oracle Databaseリリース11gでは、セマンティク・データを分析して、統計を最新に保持するために、SEM_APIS.ANALYZE_MODELSEM_APIS.ANALYZE_ENTAILMENTおよびSEM_PERF.GATHER_STATSが導入されています。これらのAPIは使用しやすく、表およびパーティション統計の内部的な詳細に関心がない一般ユーザーを対象としています。

次のサブプログラムを使用して、モデルおよび伴意の統計をエクスポート、インポート、設定および削除したり、ネットワーク統計をエクスポート、インポートおよび削除することができます。

この項では、セマンティク・モデルとセマンティク・ネットワークの統計の管理に関連する、次の内容について説明します。

1.11.1 モデル・レベルでの統計の保存

既存のモデルに対する問合せおよび推論が効率的に実行された場合、モデルの所有者として、既存のモデルの統計を保存できます。

-- Login as the model owner (for example, SCOTT)
-- Create a stats table. This is required.
execute dbms_stats.create_stat_table('scott','rdf_stat_tab');
 
-- You must grant access to MDSYS
SQL> grant select, insert, delete, update on scott.rdf_stat_tab to MDSYS;
 
-- Now export the statistics of model TEST
execute sdo_rdf.export_model_stats('TEST','rdf_stat_tab', 'model_stat_saved_on_AUG_10', true, 'SCOTT', 'OBJECT_STATS');

また、SEM_APIS.EXPORT_ENTAILMENT_STATS を使用して、伴意の統計(伴意グラフ)を保存できます。

execute sem_apis.create_entailment('test_inf',sem_models('test'),sem_rulebases('owl2rl'),0,null);
PL/SQL procedure successfully completed.
 
execute sem_apis.export_entailment_stats('TEST_INF','rdf_stat_tab', 'inf_stat_saved_on_AUG_10', true, 'SCOTT', 'OBJECT_STATS');

1.11.2 モデル・レベルでの統計のリストア

モデルの所有者として、以前にSEM_APIS.EXPORT_MODEL_STATS に保存した統計をリストアできます。これは、このモデルに更新が割り当てられ、統計が再収集された場合に必要となることがあります。統計に変更があると既存のSPARQL問合せの計画変更が生じることがあり、このような計画変更を望まない場合には、古いセットの統計をリストアできます。

execute sem_apis.import_model_stats('TEST','rdf_stat_tab', 'model_stat_saved_on_AUG_10', true, 'SCOTT', false, true, 'OBJECT_STATS');

また、SEM_APIS.IMPORT_ENTAILMENT_STATS を使用して、伴意の統計(伴意グラフ)をリストアできます。

execute sem_apis.import_entailment_stats('TEST','rdf_stat_tab', 'inf_stat_saved_on_AUG_10', true, 'SCOTT', false, true, 'OBJECT_STATS');

1.11.3 ネットワーク・レベルでの統計の保存

統計はネットワーク・レベルで保存できます。

-- First, create a user RDF_ADMIN and assign access to package SEM_PERF to RDF_ADMIN
--
-- As SYS
--
create user RDF_ADMIN identified by RDF_ADMIN;
 
grant connect, resource, unlimited tablespace to RDF_ADMIN;
 
grant execute on sem_perf to RDF_ADMIN;
 
conn RDF_ADMIN/<password>
 
execute dbms_stats.create_stat_table('RDF_ADMIN','rdf_stat_tab');
grant select, insert, delete, update on RDF_ADMIN.rdf_stat_tab to MDSYS;
 
--
-- This API call will save the statistics of both MDSYS.RDF_VALUE$ table
-- and MDSYS.RDF_LINK$
--
execute sem_perf.export_network_stats('rdf_stat_tab', 'NETWORK_ALL_saved_on_Aug_10', true, 'RDF_ADMIN', 'OBJECT_STATS');
 
--
-- Alternatively, you can save statistics of the MDSYS.RDF_VALUE$ table
--
execute sem_perf.export_network_stats('rdf_stat_tab', 'NETWORK_VALUE_TAB_saved_on_Aug_10', true, 'RDF_ADMIN', 'OBJECT_STATS', options=> mdsys.sdo_rdf.VALUE_TAB_ONLY);
 
--
-- Or, you can save statistics of the MDSYS.RDF_LINK$ table
--
execute sem_perf.export_network_stats('rdf_stat_tab', 'NETWORK_LINK_TAB_saved_on_Aug_10', true, 'RDF_ADMIN', 'OBJECT_STATS', options=> mdsys.sdo_rdf.LINK_TAB_ONLY);

1.11.4 ネットワーク・レベルでの統計のリストア

「ネットワーク・レベルでの統計の保存」の特権ユーザーは、SEM_PERF.IMPORT_NETWORK_STATSを使用して、ネットワーク・レベル統計をリストアできます。

conn RDF_ADMIN/<password>
 
execute sem_perf.import_network_stats('rdf_stat_tab', 'NETWORK_ALL_saved_on_Aug_10', true, 'RDF_ADMIN', false, true, 'OBJECT_STATS');

1.11.5 モデル・レベルでの統計の設定

モデルの所有者として、このモデルの統計を手動で調整できます。(ただし、統計を調整する前に、統計を必要に応じてリストアできるように先に保存しておく必要があります。)次の例では、モデルの行数とブロック数の2つのメトリックを設定します。

execute sem_apis.set_model_stats('TEST', numrows=>10, numblks=>1,no_invalidate=>false);

また、SEM_APIS.SET_ENTAILMENT_STATS を使用して、伴意の統計を設定できます。

execute sem_apis.set_entailment_stats('TEST_INF', numrows=>10, numblks=>1,no_invalidate=>false);

1.11.6 モデル・レベルでの統計の削除

統計の削除も実行計画に影響を及ぼすことがあります。モデルの所有者として、モデルの統計を削除できます。

execute sem_apis.delete_model_stats('TEST', no_invalidate=> false);

また、SEM_APIS.DELETE_ENTAILMENT_STATSを使用して、伴意の統計を削除できます。(ただし、モデルまたは伴意の統計を削除する前に、統計を必要に応じてリストアできるように先に保存しておく必要があります。)

execute sem_apis.delete_entailment_stats('TEST_INF', no_invalidate=> false);

1.12 セマンティク・モデルに対するSPARQL更新操作のサポート

Oracle Databaseリリース12.2では、セマンティク・モデルに対するSPARQL更新操作が可能になりました。

W3Cは、RDFグラフに対する更新言語であるSPARQL 1.1更新(https://www.w3.org/TR/2013/REC-sparql11-update-20130321/)を定めています。SPARQL 1.1更新は、SEM_APIS.UPDATE_MODELプロシージャを通じて、Oracle Databaseでサポートされています。

SPARQL更新操作を実行するには、前提となる条件がいくつかあります。

  • SEM_APIS.UPDATE_MODELプロシージャを使用することになる各ユーザーのスキーマで、SEM_APIS.CREATE_SPARQL_UPDATE_TABLESプロシージャを実行しておく必要があります。

  • SEM_APIS.UPDATE_MODELプロシージャを使用してモデルを更新しようとするユーザーには、apply_modelモデルに関連するアプリケーション表へのINSERT権限が与えられていて、なおかつMDSYSユーザーに、その表に対するINSERT権限が与えられている(たとえば、GRANT INSERT on APP_TAB1 to MDSYS;)必要があります。

    ここで、アプリケーション表は、モデルに対するセマンティク・データを参照している表です。

  • LOAD操作を実行するには、ユーザーがCREATE ANY DIRECTORYおよびDROP ANY DIRECTORY権限を持っている必要があります。

次に、RDFモデルに対する更新操作の例をいくつか示します。

例1-98 INSERT DATA操作

これは、electronicsモデルのデフォルト・グラフに複数のトリプルを挿入するINSERT DATA操作の例です。

-- Dataset before operation:
#Empty default graph
-- Update operation:
BEGIN
  sem_apis.update_model('electronics',
   'PREFIX : <http://www.example.org/electronics/> 
    INSERT DATA {
       :camera1 :name "Camera 1" .
       :camera1 :price 120 .
       :camera1 :cameraType :Camera .
       :camera2 :name "Camera 2" .
       :camera2 :price 150 .
       :camera2 :cameraType :Camera .
      } ');
END;
/

-- Dataset after operation:
@prefix : <http://www.example.org/electronics/> 
#Default graph
:camera1 :name "Camera 1";
         :price 120;
         :cameraType :Camera .
:camera2 :name "Camera 2"; 
         :price 150;
         :cameraType :Camera .

例1-99 DELETE DATA操作

これは、electronicsモデルのデフォルト・グラフからトリプルを1つ削除するDELETE DATA操作の例です。

-- Dataset before operation:
@prefix : <http://www.example.org/electronics/> 
#Default graph
:camera1 :name "Camera 1";
         :price 120;
         :cameraType :Camera .
:camera2 :name "Camera 2";
         :price 150;
         :cameraType :Camera .
-- Update operation:
BEGIN
  sem_apis.update_model('electronics',
   'PREFIX : <http://www.example.org/electronics/> 
    DELETE DATA { :camera1 :price 120 . } ');
END;
/

-- Dataset after operation:
@prefix : <http://www.example.org/electronics/> 
#Default graph
:camera1 :name "Camera 1";
         :cameraType :Camera .
:camera2 :name "Camera 2";
         :price 150;
         :cameraType :Camera .

例1-100 デフォルト・グラフに対するDELETE操作およびINSERT操作

この例ではDELETE操作およびINSERT操作を行っています。:camera1:cameraTypeが、:digitalCameraに更新されています。

-- Dataset before operation:
@prefix : <http://www.example.org/electronics/> 
#Default graph
:camera1 :name "Camera 1";
         :cameraType :Camera .
:camera2 :name "Camera 2";
         :price 150;
         :cameraType :Camera .

-- Update operation:
BEGIN
  sem_apis.update_model('electronics',
   'PREFIX : <http://www.example.org/electronics/> 
    DELETE { :camera1 :cameraType ?type . } 
    INSERT { :camera1 :cameraType :digitalCamera . } 
    WHERE  { :camera1 :cameraType ?type . }');
END;
/

-- Dataset after operation:
@prefix : <http://www.example.org/electronics/> 
#Default graph
:camera1 :name "Camera 1";
         :cameraType :digitalCamera .
:camera2 :name "Camera 2";
         :price 150;
         :cameraType :Camera .

例1-101 デフォルト・グラフおよび名前付きグラフに対するDELETE操作およびINSERT操作

グラフは、DELETEおよびINSERTテンプレートで指定することも、WHERE句の中で指定することもできます。この例では、デジタル・カメラに対応するすべてのトリプルを、デフォルト・グラフから:digitalCamerasというグラフへ移動します。

-- Dataset before operation:
@prefix : <http://www.example.org/electronics/> 
#Default graph
:camera1 :name "Camera 1";
         :cameraType :digitalCamera .
:camera2 :name "Camera 2";
         :price 150;
         :cameraType :Camera .
#Empty graph :digitalCameras

-- Update operation:
BEGIN
  sem_apis.update_model('electronics',
   'PREFIX : <http://www.example.org/electronics/> 
    DELETE { ?s ?p ?o } 
    INSERT { graph :digitalCameras { ?s ?p ?o } }
    WHERE  { ?s :cameraType :digitalCamera .
             ?s ?p ?o }');
END;
/

-- Dataset after operation:
@prefix : <http://www.example.org/electronics/> 
#Default graph
:camera2 :name "Camera 2";
         :price 150;
         :cameraType :Camera .
#Graph :digitalCameras
GRAPH :digitalCameras {
  :camera1 :name "Camera 1";
           :cameraType :digitalCamera .
}

例1-102 INSERT WHERE操作およびDELETE WHERE操作

DELETE操作またはINSERT操作から、DELETEテンプレートまたはINSERTテンプレートのいずれかを削除できます。さらに、DELETEに続くテンプレートは、WHEREパターンをDELETEテンプレートとして使用するためのショートカットとして省略できます。この例では、INSERT WHERE文を使用して、:digitalCamerasグラフのコンテンツを:camerasグラフに挿入しています。また、構文ショートカットを用いたDELETE WHERE文を使用して、:camerasグラフからすべてのコンテンツを削除しています。


-- INSERT WHERE
-- Dataset before operation:
@prefix : <http://www.example.org/electronics/> 
#Default graph
:camera2 :name "Camera 2";
         :price 150;
         :cameraType :Camera .
#Graph :digitalCameras
GRAPH :digitalCameras {
  :camera1 :name "Camera 1";
           :cameraType :digitalCamera .
}
#Empty graph :cameras

-- Update operation:
BEGIN
  sem_apis.update_model('electronics',
   'PREFIX : <http://www.example.org/electronics/> 
    INSERT { graph :cameras { ?s ?p ?o } }
    WHERE  { graph :digitalCameras { ?s ?p ?o } }');
END;
/

-- Dataset after operation:
@prefix : <http://www.example.org/electronics/> 
#Default graph
:camera2 :name "Camera 2";
         :price 150;
         :cameraType :Camera .
#Graph :digitalCameras
GRAPH :digitalCameras {
  :camera1 :name "Camera 1";
           :cameraType :digitalCamera .
}
#Graph :cameras
GRAPH :cameras {
  :camera1 :name "Camera 1";
           :cameraType :digitalCamera .
}

-- DELETE WHERE
-- Dataset before operation:
@prefix : <http://www.example.org/electronics/> 
#Default graph
:camera2 :name "Camera 2";
         :price 150;
         :cameraType :Camera .
#Graph :digitalCameras
GRAPH :digitalCameras {
  :camera1 :name "Camera 1";
           :cameraType :digitalCamera .
}
#Graph :cameras
GRAPH :cameras {
  :camera1 :name "Camera 1";
           :cameraType :digitalCamera .
}

-- Update operation:
BEGIN
  sem_apis.update_model('electronics',
   'PREFIX : <http://www.example.org/electronics/> 
    DELETE WHERE { graph :cameras { ?s ?p ?o } }');
END;
/

-- Dataset after operation:
@prefix : <http://www.example.org/electronics/> 
#Default graph
:camera2 :name "Camera 2";
         :price 150;
         :cameraType :Camera .
#Graph :digitalCameras
GRAPH :digitalCameras {
  :camera1 :name "Camera 1";
           :cameraType :digitalCamera .
}
#Empty graph :cameras

例1-103 COPY操作

この例ではCOPY操作を行っています。デフォルト・グラフから、すべてのデータが:camerasグラフに挿入されます。:camerasに既存データがある場合、そのデータは挿入前に削除されます。

-- Dataset before operation:
@prefix : <http://www.example.org/electronics/> 
#Default graph
:camera2 :name "Camera 2";
         :price 150;
         :cameraType :Camera .
#Graph :digitalCameras
GRAPH :digitalCameras {
  :camera1 :name "Camera 1";
           :cameraType :digitalCamera .
}
#Graph :cameras
GRAPH :cameras {
  :camera3 :name "Camera 3" .
}

-- Update operation:
BEGIN
  sem_apis.update_model('electronics',
   'PREFIX : <http://www.example.org/electronics/>
    COPY DEFAULT TO GRAPH :cameras');
END;
/

-- Dataset after operation:
@prefix : <http://www.example.org/electronics/> 
#Default graph
:camera2 :name "Camera 2";
         :price 150;
         :cameraType :Camera .
#Graph :digitalCameras
GRAPH :digitalCameras {
  :camera1 :name "Camera 1"; 
           :cameraType :digitalCamera .
}
#Graph :cameras
GRAPH :cameras {
  :camera2 :name "Camera 2";
           :price 150;
           :cameraType :Camera .
}

例1-104 ADD操作

この例では、:digitalCamerasグラフのデータすべてを、:camerasグラフへ追加しています。

-- Dataset before operation:
@prefix : <http://www.example.org/electronics/> 
#Default graph
:camera2 :name "Camera 2";
         :price 150;
         :cameraType :Camera .
#Graph :digitalCameras
GRAPH :digitalCameras {
  :camera1 :name "Camera 1";
           :cameraType :digitalCamera .
}
#Graph :cameras
GRAPH :cameras {
  :camera2 :name "Camera 2";
           :price 150;
           :cameraType :Camera .
}

-- Update operation:
BEGIN
  sem_apis.update_model('electronics',
   'PREFIX : <http://www.example.org/electronics/>
    ADD GRAPH :digitalCameras TO GRAPH :cameras');
END;
/

-- Dataset after operation:
@prefix : <http://www.example.org/electronics/> 
#Default graph
:camera2 :name "Camera 2";
         :price 150;
         :cameraType :Camera .
#Graph :digitalCameras
GRAPH :digitalCameras {
  :camera1 :name "Camera 1";
           :cameraType :digitalCamera .
}
#Graph :cameras
GRAPH :cameras {
  :camera1 :name "Camera 1";
           :cameraType :digitalCamera .
  :camera2 :name "Camera 2";
           :price 150;
           :cameraType :Camera .
}

例1-105 MOVE操作

この例では、:digitalCamerasグラフのデータすべてを、:digCamグラフへ移動しています。

-- Dataset before operation:
@prefix : <http://www.example.org/electronics/> 
#Default graph
:camera2 :name "Camera 2";
         :price 150;
         :cameraType :Camera .
#Graph :digitalCameras
GRAPH :digitalCameras {
  :camera1 :name "Camera 1";
           :cameraType :digitalCamera .
}
#Graph :cameras
GRAPH :cameras {
  :camera1 :name "Camera 1";
           :cameraType :digitalCamera .
  :camera2 :name "Camera 2";
           :price 150;
           :cameraType :Camera .
}
#Graph :digCam
GRAPH :digCam {
  :camera4 :cameraType :digCamera .
}

-- Update operation:
BEGIN
  sem_apis.update_model('electronics',
   'PREFIX : <http://www.example.org/electronics/>
    MOVE GRAPH :digitalCameras TO GRAPH :digCam');
END;
/

-- Dataset after operation:
@prefix : <http://www.example.org/electronics/> 
#Default graph
:camera2 :name "Camera 2" .
         :camera2 :price 150 .
         :camera2 :cameraType :Camera .
#Empty graph :digitalCameras
#Graph :cameras
GRAPH :cameras {
  :camera1 :name "Camera 1";
           :cameraType :digitalCamera .
  :camera2 :name "Camera 2";
           :price 150;
           :cameraType :Camera .
}
#Graph :digCam
GRAPH :digCam {
  :camera1 :name "Camera 1";
           :cameraType :digitalCamera .
}

例1-106 CLEAR操作

この例では、CLEAR操作を実行して、デフォルト・グラフのトリプルすべてを削除しています。RDFモデルには空のグラフは保存されないため、CLEAR操作はいつも成功します。また、この操作はDROP操作と等価です。(同じ理由で、CREATE操作はRDFモデルに何の影響も与えません。)

-- Dataset before operation:
@prefix : <http://www.example.org/electronics/> 
#Default graph
:camera2 :name "Camera 2";
         :price 150;
         :cameraType :Camera .
#Empty graph :digitalCameras
#Graph :cameras
GRAPH :cameras {
  :camera1 :name "Camera 1";
           :cameraType :digitalCamera 
  :camera2 :name "Camera 2";
           :price 150;
           :cameraType :Camera .
}
#Graph :digCam
GRAPH :digCam {
  :camera1 :name "Camera 1";
           :cameraType :digitalCamera .
}

-- Update operation:
BEGIN
  sem_apis.update_model('electronics',
   'CLEAR DEFAULT ');
END;
/

-- Dataset after operation:
@prefix : <http://www.example.org/electronics/> 
#Empty Default graph
#Empty graph :digitalCameras
#Graph :cameras
GRAPH :cameras {
  :camera1 :name "Camera 1";
           :cameraType :digitalCamera .
  :camera2 :name "Camera 2";
           :price 150;
           :cameraType :Camera .
}
#Graph :digCam
GRAPH :digCam {
  :camera1 :name "Camera 1";
           :cameraType :digitalCamera .
}

例1-107 LOAD操作

N-TripleおよびN-Quad のファイルを、ローカルのファイル・システムから、LOAD操作によってロードすることができます。オプションのINTO句を使用して、特定の名前付きグラフにファイルをロードできます。(LOAD操作の実行には、CREATE ANY DIRECTORY権限およびDROP ANY DIRECTORY権限が必要です。)この例では、N-クワッド・ファイル/home/oracle/example.nqを、セマンティク・モデルにロードしています。

なお、N-クワッド・ファイルでINTO句を使用すると、そのN-クワッド・ファイルにある名前付きグラフの情報は、すべて上書きされます。この例では、INTO GRAPH :camerasにより、最初のクワッドに対して:myGraphが上書きされるため、代わりにこのクワッドのトリプル・コンポーネントである主語、プロパティ、目的語が、:camerasグラフに挿入されます。

-- Datafile: /home/oracle/example.nq
<http://www.example.org/electronics/camera3> <http://www.example.org/electronics/name> "Camera 3" <http://www.example.org/electronics/myGraph> .
<http://www.example.org/electronics/camera3> <http://www.example.org/electronics/price> "125"^^<http://www.w3.org/2001/XMLSchema#decimal> .

-- Dataset before operation:
#Graph :cameras
GRAPH :cameras {
  :camera1 :name "Camera 1";
           :cameraType :digitalCamera .
  :camera2 :name "Camera 2";
           :price 150;
           :cameraType :Camera .
}
#Graph :digCam
GRAPH :digCam {
  :camera1 :name "Camera 1";
           :cameraType :digitalCamera .
}

-- Update operation:
BEGIN
  sem_apis.update_model('electronics',
   'PREFIX : <http://www.example.org/electronics/>
    LOAD <file:///home/oracle/example.nq> INTO GRAPH :cameras');
END;
/

-- Dataset after operation:
@prefix : <http://www.example.org/electronics/> 
#Graph :cameras
GRAPH :cameras {
  :camera1 :name "Camera 1";
           :cameraType :digitalCamera .
  :camera2 :name "Camera 2";
           :price 150;
           :cameraType :Camera .
  :camera3 :name "Camera 3";
           :price 125.
}
#Graph :digCam
GRAPH :digCam {
  :camera1 :name "Camera 1";
           :cameraType :digitalCamera .
}

1回のLOAD操作で、同じディレクトリのファイルを複数、並行してロードできます。追加のN-TripleまたはN-Quadのファイルをロードするために、LOAD_OPTIONSヒントを使用できます。ファイル数と等しい並列度を使用することで、ファイルを並行してロードすることができます。次の例では、ファイル/home/oracle/example1.nq/home/oracle/example2.nqおよび/home/oracle/example3.nqを、セマンティク・モデルにロードする方法を示します。この例では、並列度3が自動的に用いられます。

BEGIN
  sem_apis.update_model('electronics',
   'PREFIX : <http://www.example.org/electronics/>
    LOAD <file:///home/oracle/example1.nq>',
   options=> ' LOAD_OPTIONS={ example2.nq example3.nq } ' );
END;
/

関連項目:

1.12.1 SPARQL更新操作の調整

場合によっては、SPARQL更新操作を調整しなければならないことがあります。SPARQL更新操作では、1つまたは複数のSPARQL問合せがUPDATE文のWHERE句に基づいて実行されるため、SPARQL更新操作には、「問合せパフォーマンスのベスト・プラクティス」もあてはまります。また、次の点にも留意する必要があります。

  • 削除の操作で高いパフォーマンスを得るためには、アプリケーション表に対する適切な索引(SEM_APIS.UPDATE_MODELapply_modelモデルに関連付けられた索引)が必要です。TRIPLEという名前のSDO_RDF_TRIPLE_S列を持つAPP_TABという名前のアプリケーション表を考えた場合、次のような索引が有効です(これは「RDF Semantic Graph Support for Apache Jena」で使用されている索引と同じです)。

    -- Application table index for 
    --  (graph_id, subject_id, predicate_id, canonical_object_id)
    CREATE INDEX app_tab_idx ON app_tab app (
      BITAND(app.triple.rdf_m_id,79228162514264337589248983040)/4294967296,
      app.triple.rdf_s_id,
      app.triple.rdf_p_id,
      app.triple.rdf_c_id)
    COMPRESS;
    
  • パフォーマンスに関係するSEM_MATCHオプションを、SEM_APIS.UPDATE_MODELmatch_optionsパラメータへ渡すことができます。また、PARALLELやDYNAMIC_SAMPLINGのようなパフォーマンスに関係するオプションを、そのプロシージャのoptionsパラメータで指定することができます。次の例では、更新に対し、オプション・パラメータを使用して並列度を4に、またオプティマイザの動的サンプリング・レベルを6に設定しています。さらにこの例では、仮想モデルVM1に対する照合で、ALLOW_DUP=Tが照合オプションとして使用されています。

    BEGIN
      sem_apis.update_model(
       'electronics',
       'PREFIX : <http://www.example.org/electronics/> 
        INSERT { graph :digitalCameras { ?s ?p ?o } }
        WHERE  { ?s :cameraType :digitalCamera .
                 ?s ?p ?o }',
       match_models=>sem_models('VM1'),
       match_options=>' ALLOW_DUP=T ',
       options=>' PARALLEL(4) DYNAMIC_SAMPLING(6) ');
    END;
    /
    
  • インライン問合せオプティマイザ・ヒントをWHERE句で指定できます。次の例では、先の例を拡張して、HINT0ヒントをWHERE句で、FINAL_VALUE_NLヒントをmatch_optionsパラメータで使用しています。

    BEGIN
      sem_apis.update_model(
       'electronics',
       'PREFIX : <http://www.example.org/electronics/> 
        INSERT { graph :digitalCameras { ?s ?p ?o } }
        WHERE  { # HINT0={ LEADING(t0 t1) USE_NL(t0 t1)
                 ?s :cameraType :digitalCamera .
                 ?s ?p ?o }',
       match_models=>sem_models('VM1'),
       match_options=>' ALLOW_DUP=T FINAL_VALUE_NL ',
       options=>' PARALLEL(4) DYNAMIC_SAMPLING(6) ');
    END;
    /
    

1.12.2 SPARQL更新操作でのトランザクション管理

SEM_APIS.UPDATE_MODEL操作で使用されるトランザクションの数、およびそれらが自動的にコミットされるのかを、ある程度制御することができます。

デフォルトでは、SEM_APIS.UPDATE_MODELプロシージャは、正常終了後にコミットされたかエラー発生時にロール・バックされた単一のトランザクションで実行されます。たとえば、次に示す呼出しでは、3つの更新操作(セミコロンで分離)が、1つのトランザクションで実行されています。

BEGIN
  sem_apis.update_model('electronics',
   'PREFIX elec: <http://www.example.org/electronics/>
    PREFIX ecom: <http://www.example.org/ecommerce/> 
    # insert camera data
    INSERT DATA {
      elec:camera1 elec:name "Camera 1" .
      elec:camera1 elec:price 120 .
      elec:camera1 elec:cameraType elec:DigitalCamera .
      elec:camera2 elec:name "Camera 2" .
      elec:camera2 elec:price 150 .
      elec:camera2 elec:cameraType elec:DigitalCamera . }; 
    # insert ecom:price triples
    INSERT { ?c  ecom:price ?p }
    WHERE  { ?c  elec:price ?p };
    # delete elec:price triples
    DELETE WHERE { ?c elec:price ?p }');
END;
/

PL/SQL procedure successfully completed.

一方、次の例では、3つのSEM_APIS.UPDATE_MODEL呼出しを別々に実行して、別個のトランザクション3つで、3つの同じ更新操作を実行しています。

BEGIN
  sem_apis.update_model('electronics',
   'PREFIX elec: <http://www.example.org/electronics/>
    PREFIX ecom: <http://www.example.org/ecommerce/> 
    # insert camera data
    INSERT DATA {
      elec:camera1 elec:name "Camera 1" .
      elec:camera1 elec:price 120 .
      elec:camera1 elec:cameraType elec:DigitalCamera .
      elec:camera2 elec:name "Camera 2" .
      elec:camera2 elec:price 150 .
      elec:camera2 elec:cameraType elec:DigitalCamera . }');
END;
/

PL/SQL procedure successfully completed.

BEGIN
  sem_apis.update_model('electronics',
   'PREFIX elec: <http://www.example.org/electronics/>
    PREFIX ecom: <http://www.example.org/ecommerce/> 
    # insert ecom:price triples
    INSERT { ?c  ecom:price ?p }
    WHERE  { ?c  elec:price ?p }');
END;
/

PL/SQL procedure successfully completed.

BEGIN
  sem_apis.update_model('electronics',
   'PREFIX elec: <http://www.example.org/electronics/>
    PREFIX ecom: <http://www.example.org/ecommerce/> 
    # insert elec:price triples
    DELETE WHERE { ?c elec:price ?p }');
END;
/

PL/SQL procedure successfully completed.

AUTOCOMMIT=Fオプションを使用して、各々のSEM_APIS.UPDATE_MODEL呼出しに、別々のトランザクションが割り当てられるのを防ぐことができます。このオプションでは、トランザクションの管理は、呼出し側の責任です。更新操作を、先の例で3つの分離したトランザクションではなく、単一のトランザクションとして実行する方法を、次の例に示します。

BEGIN
  sem_apis.update_model('electronics',
   'PREFIX elec: <http://www.example.org/electronics/>
    PREFIX ecom: <http://www.example.org/ecommerce/> 
    # insert camera data
    INSERT DATA {
      elec:camera1 elec:name "Camera 1" .
      elec:camera1 elec:price 120 .
      elec:camera1 elec:cameraType elec:DigitalCamera .
      elec:camera2 elec:name "Camera 2" .
      elec:camera2 elec:price 150 .
      elec:camera2 elec:cameraType elec:DigitalCamera . }',
   options=>' AUTOCOMMIT=F ');
END;
/

PL/SQL procedure successfully completed.

BEGIN
  sem_apis.update_model('electronics',
   'PREFIX elec: <http://www.example.org/electronics/>
    PREFIX ecom: <http://www.example.org/ecommerce/> 
    # insert ecom:price triples
    INSERT { ?c  ecom:price ?p }
    WHERE  { ?c  elec:price ?p }',
   options=>' AUTOCOMMIT=F ');
END;
/

PL/SQL procedure successfully completed.

BEGIN
  sem_apis.update_model('electronics',
   'PREFIX elec: <http://www.example.org/electronics/>
    PREFIX ecom: <http://www.example.org/ecommerce/> 
    # insert elec:price triples
    DELETE WHERE { ?c elec:price ?p }',
   options=>' AUTOCOMMIT=F ');
END;
/

PL/SQL procedure successfully completed.

COMMIT;

Commit complete.

ただし、AUTOCOMMIT=Fオプションでは、次のことはできません。

  • バルク操作(FORCE_BULK=TDEL_AS_INS=T)

  • LOAD操作

  • 中間データの実体化(STREAMING=F)

1.12.2.1 トランザクション分離レベル

Oracle Databaseは3つのトランザクション分離レベル(読取りコミット、シリアライズ可能、読取り専用)に対応しています。

読取りコミット分離レベルがデフォルトです。この分離レベルを使用したトランザクションでは、問合せ(そのトランザクションではなく)の開始前にコミットされたデータ、またはトランザクション自体により行われた変更のみが問合せの対象になります。この分離レベルを用いることで、同時実効性を最も高くすることができます。

シリアライズ可能分離レベルを使用したトランザクションでは、問合せの開始前にコミットされたデータ、またはトランザクション自体により行われた変更のみが問合せの対象になります。

読取り専用分離レベルは、シリアライズ可能分離レベルと動作が似ていますが、トランザクションによってデータを修正することはできません。

SEM_APIS.UPDATE_MODELは、読取りコミットおよびシリアル化可能のトランザクション分離レベルに対応しており、読取りコミットがデフォルトです。SPARQL UPDATE操作は、次の基本的ステップに従って処理されます。

  1. 削除するトリプルのセットを取得する問合せが実行されます。

  2. 挿入するトリプルのセットを取得する問合せが実行されます。

  3. ステップ1で取得されたトリプルが削除されます。

  4. ステップ2で取得されたトリプルが挿入されます。

デフォルトの読取りコミット分離レベルでは、同時実行されるトランザクションにより基礎となるトリプル・データに変更が加えられることがあるため、各ステップで異なるデータが対象となる可能性があります。さらに、同時実行されるトランザクションにより加えられる変更は、同じSEM_APIS.UPDATE_MODEL呼び出しで実行されるその後の更新操作の対象となります。なお、中間データの実体化を使用すると(STREAMING=F)、ステップ1とステップ2は1つのステップとして実行されるため、このオプションでは、ステップ1とステップ2の間で、基礎となるトリプル・データに変更を加えることはできません。中間データの実体化に関する詳細は、「バルク操作のサポート」を参照してください。

シリアライズ可能分離レベルは、オプションSERIALIZABLE=Tを指定することで使用できます。その場合、各ステップの対象は、モデルの更新操作が始まる前にコミットされたデータのみであり、他のトランザクションで並行して実行される更新操作により加えられる変更は、1回のSEM_APIS.UPDATE_MODEL呼出しで複数実行される更新操作の対象にはなりません。ただし、SEM_APIS.UPDATE_MODELの実行によって、並行するトランザクションで変更されたトリプルに対し更新が試行されると、ORA-08177エラーが発生します。SERIALIZABLE=Tを使用する場合、ORA-08177エラーがアプリケーションにより検知され、処理される必要があります(たとえば、最初の試行でシリアル化できなかった場合の更新コマンド再試行)。

次の操作を、SERIALIZABLE=Tオプションとともに使用することはできません。

  • バルク操作(FORCE_BULK=TDEL_AS_INS=T)

  • LOAD操作

  • 中間データの実体化(STREAMING=F)

1.12.3 バルク操作のサポート

SEM_APIS.UPDATE_MODELは、大量の更新を効率的に実行するバルク操作に対応しています。次のオプションが利用可能です。ただし、そうしたバルク操作を実行する場合には、シリアル化可能分離(SERIALIZABLE=T)および自動コミットの抑制(AUTOCOMMMIT=F)は使用できません。

1.12.3.1 中間データの実体化(STREAMING=F)(STREAMING=F)

デフォルトでは、SEM_APIS.UPDATE_MODELの実行により、基本的なDELETE INSERT SPARQL更新操作に対し2つの問合せ(削除するトリプルを探す問合せと、挿入するトリプルを探す問合せ)が実行されます。評価に時間のかかるWHERE句を含む更新操作を行う場合、2つの問合せを実行することは最も良いパフォーマンスにつながらないことがあります。そうした場合、WHERE句に対して1回の問合せを実行し、結果を実体化した後、実体化した結果を用いて、削除するトリプルおよび挿入するトリプルの構築を行う方が、より良いパフォーマンスを得られることがあります。この方法ではDDL操作によるオーバーヘッドが生じますが、複雑な更新文の場合には、全体としてパフォーマンスの向上が期待できます。

次に示す更新の例では、このオプション(STREAMING=F)が使用されています。なお、STREAMING=Fは、シリアル化可能分離(SERIALIZABLE=T)あるいは自動コミット抑制(AUTOCOMMIT=F)と同時には使用できません。

BEGIN
  sem_apis.update_model('electronics',
   'PREFIX : <http://www.example.org/electronics/> 
    DELETE { ?s ?p ?o } 
    INSERT { graph :digitalCameras { ?s ?p ?o } }
    WHERE  { ?s :cameraType :digitalCamera .
             ?s ?p ?o }',
  options=>' STREAMING=F ');
END;
/
1.12.3.2 SEM_APIS.BULK_LOAD_FROM_STAGING_TABLEの使用

大量のトリプル(万単位のような)を挿入する更新の場合、アプリケーション表に対する増分DMLというデフォルトの方法では、十分なパフォーマンスを得られないことがあります。そのような場合、FORCE_BULK=Tオプションを指定して、増分DMLではなくSEM_APIS.BULK_LOAD_FROM_STAGING_TABLEが使用されるようにすることができます。

ただし、すべての更新操作でこの最適化を使用できるわけではありません。FORCE_BULK=Tオプションは、単一のADD操作または単一のINSERT WHERE操作を含むSEM_APIS.UPDATE_MODEL呼出しに対してのみ使用可能です。SEM_APIS.BULK_LOAD_FROM_STAGING_TABLEにより、一連のコミットおよび自律的なトランザクションが発生するため、AUTOCOMMIT=FおよびSERIALIZABLE=Tオプションは、FORCE_BULK=Tと同時に使用できません。さらに、バルク・ロードはCLOB_UPDATE_SUPPORT=Tと同時に使用できません。

SEM_APIS.BULK_LOAD_FROM_STAGING_TABLEは、その中のflagsパラメータを用いて、様々にカスタマイズできます。SEM_APIS.UPDATE_MODELは、BULK_OPTIONS={ OPTIONS_STRING }フラグに対応しているため、OPTIONS_STRINGSEM_APIS.BULK_LOAD_FROM_STAGING_TABLEflagsインプットに渡して、バルク・ロードのオプションをカスタマイズできます。次の例に、FORCE_BULK=Tオプション、およびBULK_OPTIONSフラグを使用したSEM_APIS.UPDATE_MODELの呼出しを示します。

BEGIN
  sem_apis.update_model('electronics',
   'PREFIX elec: <http://www.example.org/electronics/>
    PREFIX ecom: <http://www.example.org/ecommerce/> 
    INSERT { ?c  ecom:price ?p }
    WHERE  { ?c  elec:price ?p }',
   options=>' FORCE_BULK=T BULK_OPTIONS={  parallel=4 parallel_create_index } ');
END;
/
1.12.3.3 挿入としての削除の使用(DEL_AS_INS=T)

大量のトリプル(何万もの)を削除する更新の場合、アプリケーション表に対する増分DMLというデフォルトの方法では、十分なパフォーマンスを得られないことがあります。その場合、DEL_AS_INS=Tを指定できます。このオプションを使用すると、大規模な削除の操作が、INSERT、TRUNCATE、そしてEXCHANGE PARTITIONの操作として実行されます。

DEL_AS_INS=Tを使用すると一連のコミットおよび自律的なトランザクションが発生するため、このオプションは、SERIALIZABLE=Tまたは AUTOCOMMIT=Fと同時に使用できません。さらに、このオプションは、単一のDELETE WHERE操作、単一のDROP操作、あるいは単一のCLEAR操作が含まれたSEM_APIS.UPDATE_MODEL呼出しと組合わせた場合にのみ使用することができます。

挿入としての削除では、中間操作でSEM_APIS.MERGE_MODELSが内部的に使用されています。OPTIONS_STRINGの文字列を、MM_OPTIONS={ OPTIONS_STRING }フラグから指定して、マージのオプションをカスタマイズすることができます。次の例で、DEL_AS_INS=TオプションおよびMM_OPTIONSフラグを使用したSEM_APIS.UPDATE_MODELの呼出しを示します。

BEGIN
  sem_apis.update_model('electronics',
   'CLEAR NAMED',
   options=>' DEL_AS_INS=T MM_OPTIONS={  dop=4 } ');
END;
/

1.12.4 セッション・レベルでのUPDATE_MODELオプションの設定

SEM_APIS.UPDATE_MODELプロシージャの動作に影響を与える設定の中には、特殊なMDSYS.SDO_SEM_UPDATE_CTX.SET_PARAMプロシージャを使用して、セッション・レベルで修正できるものがあります。autocommitstreamingstrict_bnodeおよびclob_supportの各オプションは、セッション・レベルでtrueまたはfalseに設定できます。

MDSYS.SDO_SEM_UPDATE_CTXには、SEM_APIS.UPDATE_MODELパラメータをセッション・レベルで取得し、設定する次のサブプログラムが含まれています。

SQL> describe mdsys.sdo_sem_update_ctx
FUNCTION GET_PARAM RETURNS VARCHAR2
 Argument Name                  Type                    In/Out Default?
 ------------------------------ ----------------------- ------ --------
 NAME                           VARCHAR2                IN
PROCEDURE SET_PARAM
 Argument Name                  Type                    In/Out Default?
 ------------------------------ ----------------------- ------ --------
 NAME                           VARCHAR2                IN
 VALUE                          VARCHAR2                IN

次の例では、AUTOCOMMIT=Fを使用するSEM_APIS.UPDATE_MODELプロシージャに対するすべての呼出しをこの後、セッションの終わりまで、あるいは異なるautocommit値を指定する次のSEM_APIS.UPDATE_MODEL呼出しまで、発生させています。

begin
  mdsys.sdo_sem_update_ctx.set_param('autocommit','false');
end;
/

1.12.5 ロード操作: SPARQL更新で特に留意する点

ロード操作がSEM_APIS.UPDATE_MODELプロシージャを用いて行われ、ロードされたドキュメントに4000バイトを超える長さの値が含まれている場合、そのような値を含むトリプルはモデルに挿入されません。ロードが終了すると、「.bad」という拡張子の付いたファイルが、ロードされたドキュメントと同じディレクトリに作成されます。拡張子.badの付いたファイルには、長い値を持トリプルが含まれています。そうしたトリプルは、「INSERT文を使用したセマンティク・データのロード」で説明されているようなINSERT文で挿入することもできれば、CLOB_UPDATE_SUPPORT=Tオプションを付けたSEM_APIS.UPDATE_MODELプロシージャを通して実行されるINSERT DATA文で挿入することもできます。

ロード操作を実行するには、そのドキュメントのトリプルを、その時のスキーマで作成されたステージング表へロードします。ロード操作が中断したものの、ステージング表がすでに作成されている場合は、optionsパラメータでRESUME_LOAD=Tキーワードを指定しておくことで、ロードを再開できます。

1.12.6 ロング・リテラル: SPARQL更新で特に留意する点

デフォルトでは、SPARQL更新で4000バイトよりも長い値が操作されることはありません。ロング・リテラルへの対応を有効にするには、SEM_APIS.UPDATE_MODELプロシージャのオプション・パラメータで、CLOB_UPDATE_SUPPORT=Tを指定します。

ロング・リテラルのバルク・ロードはできません。CLOB_UPDATE_SUPPORT=Tオプションが同時に指定されている場合には、FORCE_BULK=Tオプションは無視されます。

1.12.7 空白のノード: SPARQL更新で特に留意する点

更新操作の中には、1セットのRDFトリプルからなるグラフに影響を与えるだけのものがあります。具体的には、ADD、COPYおよびMOVEといった操作です。たとえば、「セマンティク・モデルでのSPARQL更新操作のサポート」で示されているMOVE操作の例では、:digitalCamerasをグラフとして持つトリプルの更新を行うことができるだけです。ただし、そうした操作のパフォーマンスは、IDに限定した操作をRDFモデルに対して行うことで向上します。大規模なADD、COPYまたはMOVE操作をID限定操作として実行するために、SEM_APIS.UPDATE_MODELプロシージャのoptionsパラメータで、STRICT_BNODE=Fヒントを指定できます。

しかし、ID限定操作の結果、正しくない空白ノードが生ずることがあります。これは、2つのグラフで同じ空白ノードが共有されることがないためです。RDFセマンティク・グラフでは、空白ノードを含むモデルとグラフの組合せに基づく空白ノード接頭辞スキームが使用されています。この接頭辞によって、モデルおよびグラフ全体におけるノード識別子の一意性が保証されています。ADD、COPYおよびUPDATE操作をID限定で行うという方法では、空白ノード接頭辞が更新されません。

例1-108 ID限定更新による誤った空白ノード値の発生

次の例に示す更新では、グラフ:camerasおよび:cameras2のトリプル両方に対して、同じ空白ノードの主語が生じます。このことは、ここで示されているSEM_MATCH問合せを実行することで確かめられます。

BEGIN
  sem_apis.update_model('electronics',
   'PREFIX : <http://www.example.org/electronics/> 
    INSERT DATA { 
       GRAPH :cameras { :camera2 :owner _:bn1 .
                        _:bn1 :name "Axel" }
    };
    COPY :cameras TO :cameras2',
   options=>' STRICT_BNODE=F ');
END;
/

SELECT count(s)
FROM TABLE( SEM_MATCH('
  PREFIX : <http://www.example.org/electronics/> 
  SELECT * 
  WHERE { { graph :cameras  {?s :name "Axel"  } }
          { graph :cameras2 {?s :name "Axel"  } } }
', sem_models('electronics'),null,null,null,null,' STRICT_DEFAULT=T '));

ADD、COPYまたはMOVE更新操作の対象に空白ノードが含まれていないことがわかっている場合、そのようなエラーを防ぐには、SEM_APIS.UPDATE_MODELプロシージャのoptionsパラメータで、STRICT_BNODE=Fヒントを指定します。

ただし、大規模なグラフに対するADD、COPYおよびMOVEの操作では、デフォルトの方法よりも、STRICT_BNODE=Fオプションを用いた方が、実行速度が大幅に早くなります。ID限定の更新を行う必要がある場合、もう1つの方法は、STRICT_BNODE=Fオプションを使用してから、最後にSEM_APIS.CLEANUP_BNODESプロシージャを実行することです。この方法では、与えられたモデルの空白ノードすべての接頭辞がリセットされ、誤った空白ノードのラベルすべてが効果的に修正(「クリーン・アップ」)されます。

なお、ADD、COPYまたはMOVE操作の回数が少ない場合には、この2段階からなる方法は用いないでください。少数の操作をデフォルトの方法を用いて実行する方が、少数のID限定操作を実行してからSEM_APIS.CLEANUP_BNODESプロシージャを実行するよりも高速です。

次の例では、electronicsという名前のセマンティク・モデルの空白ノードを修正しています。

EXECUTE sem_apis.cleanup_bnodes('electronics');

1.13 強化されたRDF ORDER BY問合せ処理

Oracle Databaseリリース12.2では、SPARQL ORDER BYセマンティクを使用するRDFデータの処理効率が、以前のリリースに比べて向上しています。

この内部処理の効率向上には、MDSYS.RDF_VALUE$メタデータ表(「文」を参照)のORDER_TYPE列、ORDER_NUM列およびORDER_DATE列が関与しています。この3つの列に対する値はロード中に格納されるため、ORDER BY問合せでの内部関数呼出しの低減と、実行時間の短縮が可能になります。

Oracle Databaseリリース12.2では、プロシージャSEM_APIS.ADD_DATATYPE_INDEXにより、以前のバージョンのように関数ベースの索引が作成されるのではなく、数値型(xsd:float、xsd:doubleおよびxsd:decimalとそのサブタイプ)のORDER_NUM列に対する索引と、日付に関連する型(xsd:date、xsd:timeおよびxsd:dateTime)のORDER_DATE列に対する索引が作成されます。こうしたデータ形に対して引続き関数ベースの索引を使用する場合には、SEM_APIS.ADD_DATATYPE_INDEXプロシージャのFUNCTION=Tオプションを使用する必要があります。たとえば、次のようにします。

EXECUTE sem_apis.add_datatype_index('http://www.w3.org/2001/XMLSchema#decimal', options=>'FUNCTION=T');
EXECUTE sem_apis.add_datatype_index('http://www.w3.org/2001/XMLSchema#date',options=>'FUNCTION=T');

1.14 セマンティク・データを使用するためのクイック・スタート

Oracle Databaseのセマンティク・データを操作するには、次の一般的なステップに従います。

  1. システム表の表領域を作成します。表領域を作成する適切な権限を持つユーザーとして接続している必要があります。次の例では、RDF_TBLSPACEという表領域を作成します。
    CREATE TABLESPACE rdf_tblspace
     DATAFILE '/oradata/orcl/rdf_tblspace.dat' SIZE 1024M REUSE
     AUTOEXTEND ON NEXT 256M MAXSIZE UNLIMITED
     SEGMENT SPACE MANAGEMENT AUTO;
    
  2. セマンティク・データ・ネットワークを作成します。

    セマンティク・データ・ネットワークを作成すると、Oracle Databaseにセマンティク・データ・サポートが追加されます。十分な領域を備えた有効な表領域を指定することで、DBA権限を持つユーザーとしてセマンティク・データ・ネットワークを作成する必要があります。このネットワークは、1つのOracle Databaseに対して1回のみ作成します。

    次の例では、RDF_TBLSPACEという表領域を使用してセマンティク・データ・ネットワークを作成します(RDF_TBLSPACEはすでに存在している必要があります)。

    EXECUTE SEM_APIS.CREATE_SEM_NETWORK('rdf_tblspace');
    
  3. セマンティク・データの格納先となるスキーマを保有するデータベース・ユーザーとして接続します(SYS、SYSTEMまたはMDSYSとして接続している場合は、次のステップを実行しないでください)。
  4. セマンティク・データへの参照を格納する表を作成します。(このステップと残りのステップでは、DBA権限を持つユーザーとして接続している必要はありません。)

    この表には、単一のモデルに関連付けられたすべてのデータへの参照を保持するSDO_RDF_TRIPLE_S型の列が含まれる必要があります。

    次の例では、トリプルのデータを保持する列を1つ含むARTICLES_RDF_DATAという名前の付いた表が作成されます。

    CREATE TABLE articles_rdf_data (triple SDO_RDF_TRIPLE_S);
    
  5. モデルを作成します。

    モデルを作成する場合、モデル名、モデルのセマンティク・データへの参照を保持する表、およびその表内のSDO_RDF_TRIPLE_S型の列を指定します。

    次のコマンドでは、前のステップで作成した表を使用するARTICLESというモデルを作成します。

    EXECUTE SEM_APIS.CREATE_SEM_MODEL('articles', 'articles_rdf_data', 'triple');
    

モデルを作成した後は、表にトリプルを挿入できます(「セマンティク・データの例(PL/SQLおよびJava)」を参照)。

1.15 セマンティク・データの例(PL/SQLおよびJava)

このガイドではPL/SQLの例が示されています。

このガイドで示されている例の他に、http://www.oracle.com/technetwork/indexes/samplecode/semantic-sample-522114.htmlのサンプル・コードを参照してください。

1.15.1 例: 雑誌記事の情報

この項では、雑誌記事に関する文のモデルに対応する簡単なPL/SQLの例を示します。例1-109では、説明のためのコメントとともに、この章で説明されている各概念が参照され、「SEM_APISパッケージ・サブプログラム」で述べられている関数とプロシージャが使用されています。

例1-109 雑誌記事の情報に関するモデルの使用

-- Basic steps:
-- After you have connected as a privileged user and called 
-- SEM_APIS.CREATE_SEM_NETWORK to add RDF support,
-- connect as a regular database user and do the following.
-- 1. For each desired model, create a table to hold its data.
-- 2. For each model, create a model (SEM_APIS.CREATE_SEM_MODEL).
-- 3. For each table to hold semantic data, insert data into the table.
-- 4. Use various subprograms and constructors.
 
-- Create the table to hold data for the model. Only one column: data for triples.
CREATE TABLE articles_rdf_data (triple SDO_RDF_TRIPLE_S);
 
-- Create the model.
EXECUTE SEM_APIS.CREATE_SEM_MODEL('articles', 'articles_rdf_data', 'triple');
 
-- Information to be stored about some fictitious articles:
-- Article1, titled "All about XYZ" and written by Jane Smith, refers 
--   to Article2 and Article3.
-- Article2, titled "A review of ABC" and written by Joe Bloggs, 
--   refers to Article3.
-- Seven SQL statements to store the information. In each statement:
-- Each article is referred to by its complete URI The URIs in
--   this example are fictitious.
-- Each property is referred to by the URL for its definition, as 
--   created by the Dublin Core Metadata Initiative.
 
-- Insert rows into the table.
 
-- Article1 has the title "All about XYZ".
INSERT INTO articles_rdf_data VALUES (
  SDO_RDF_TRIPLE_S ('articles','<http://nature.example.com/Article1>',
    '<http://purl.org/dc/elements/1.1/title>','"All about XYZ"'));
 
-- Article1 was created (written) by Jane Smith.
INSERT INTO articles_rdf_data VALUES (
  SDO_RDF_TRIPLE_S ('articles','<http://nature.example.com/Article1>',
    '<http://purl.org/dc/elements/1.1/creator>',
    '"Jane Smith"'));
 
-- Article1 references (refers to) Article2.
INSERT INTO articles_rdf_data VALUES (
  SDO_RDF_TRIPLE_S ('articles',
    '<http://nature.example.com/Article1>',
    '<http://purl.org/dc/terms/references>',
    '<http://nature.example.com/Article2>'));
 
-- Article1 references (refers to) Article3.
INSERT INTO articles_rdf_data VALUES (
  SDO_RDF_TRIPLE_S ('articles',
    '<http://nature.example.com/Article1>',
    '<http://purl.org/dc/terms/references>',
    '<http://nature.example.com/Article3>'));
 
-- Article2 has the title "A review of ABC".
INSERT INTO articles_rdf_data VALUES (
  SDO_RDF_TRIPLE_S ('articles',
    '<http://nature.example.com/Article2>',
    '<http://purl.org/dc/elements/1.1/title>',
    '"A review of ABC"'));
 
-- Article2 was created (written) by Joe Bloggs.
INSERT INTO articles_rdf_data VALUES (
  SDO_RDF_TRIPLE_S ('articles',
    '<http://nature.example.com/Article2>',
    '<http://purl.org/dc/elements/1.1/creator>',
    '"Joe Bloggs"'));
 
-- Article2 references (refers to) Article3.
INSERT INTO articles_rdf_data VALUES (
  SDO_RDF_TRIPLE_S ('articles',
    '<http://nature.example.com/Article2>',
    '<http://purl.org/dc/terms/references>',
    '<http://nature.example.com/Article3>'));
 
COMMIT;
 
-- Query semantic data.
 
SELECT SEM_APIS.GET_MODEL_ID('articles') AS model_id FROM DUAL;
 
SELECT SEM_APIS.GET_TRIPLE_ID(
  'articles',
  '<http://nature.example.com/Article2>',
  '<http://purl.org/dc/terms/references>',
  '<http://nature.example.com/Article3>') AS RDF_triple_id FROM DUAL;
 
SELECT SEM_APIS.IS_TRIPLE(
  'articles',
  '<http://nature.example.com/Article2>',
  '<http://purl.org/dc/terms/references>',
  '<http://nature.example.com/Article3>') AS is_triple FROM DUAL;
 
-- Use SDO_RDF_TRIPLE_S member functions in queries.
 
-- Find all articles that reference Article2.
SELECT a.triple.GET_SUBJECT() AS subject
  FROM articles_rdf_data a
  WHERE a.triple.GET_PROPERTY() = '<http://purl.org/dc/terms/references>' AND
    TO_CHAR(a.triple.GET_OBJECT()) = '<http://nature.example.com/Article2>';

-- Find all triples with Article1 as subject.
SELECT a.triple.GET_TRIPLE() AS triple
  FROM articles_rdf_data a
  WHERE a.triple.GET_SUBJECT() = '<http://nature.example.com/Article1>';

-- Find all objects where the subject is Article1.
SELECT a.triple.GET_OBJECT() AS object 
  FROM articles_rdf_data a 
WHERE a.triple.GET_SUBJECT() = '<http://nature.example.com/Article1>';

-- Find all triples where Jane Smith is the object.
SELECT a.triple.GET_TRIPLE() AS triple
  FROM articles_rdf_data a 
  WHERE TO_CHAR(a.triple.GET_OBJECT()) = '"Jane Smith"';

1.15.2 例: 家系の情報

この項では、ファミリ・ツリー(家系)情報に関する文のモデルに対応する簡単なPL/SQLの例を示します。例1-109では、説明のためのコメントとともに、この章で説明されている各概念が参照され、「SEM_APISパッケージ・サブプログラム」で述べられている関数とプロシージャが使用されています。

この例の家族関係は、図1-3のファミリ・ツリーを反映しています。また、この図では、例における一部の情報(CathyはJackの姉妹、JackとTomは男性、Cindyは女性)が直接言明されています。

図1-3 RDFの例のファミリ・ツリー

図1-3の説明が続きます
「図1-3 RDFの例のファミリ・ツリー」の説明

例1-110 家系の情報に関するモデルの使用

-- Preparation: create tablespace; enable RDF support.
-- Connect as a privileged user. Example: CONNECT SYSTEM/password-for-SYSTEM
-- Create a tablespace for the RDF data. Example:
CREATE TABLESPACE rdf_tblspace 
  DATAFILE 'rdf_tblspace.dat' 
    SIZE 128M REUSE
    AUTOEXTEND ON NEXT 128M MAXSIZE 4G
  SEGMENT SPACE MANAGEMENT AUTO;

-- Call SEM_APIS.CREATE_SEM_NETWORK to enable RDF support. Example:
EXECUTE SEM_APIS.CREATE_SEM_NETWORK('rdf_tblspace');

-- Connect as the user that is to perform the RDF operations (not SYSTEM), 
-- and do the following:
-- 1. For each desired model, create a table to hold its data.
-- 2. For each model, create a model (SEM_APIS.CREATE_SEM_MODEL).
-- 3. For each table to hold semantic data, insert data into the table.
-- 4. Use various subprograms and constructors.

-- Create the table to hold data for the model.
CREATE TABLE family_rdf_data (triple SDO_RDF_TRIPLE_S);
 
-- Create the model.
execute SEM_APIS.create_sem_model('family', 'family_rdf_data', 'triple');
 
-- Insert rows into the table. These express the following information:
-----------------
-- John and Janice have two children, Suzie and Matt.
-- Matt married Martha, and they have two children:
--   Tom (male, height 5.75) and Cindy (female, height 06.00).
-- Suzie married Sammy, and they have two children:
--   Cathy (height 5.8) and Jack (male, height 6).
 
-- Person is a class that has two subslasses: Male and Female.
-- parentOf is a property that has two subproperties: fatherOf and motherOf.
-- siblingOf is a property that has two subproperties: brotherOf and sisterOf.
-- The domain of the fatherOf and brotherOf properties is Male.
-- The domain of the motherOf and sisterOf properties is Female.
------------------------
 
-- John is the father of Suzie.
INSERT INTO family_rdf_data VALUES ( 
SDO_RDF_TRIPLE_S('family', 
'<http://www.example.org/family/John>', 
'<http://www.example.org/family/fatherOf>', 
'<http://www.example.org/family/Suzie>'));
 
-- John is the father of Matt.
INSERT INTO family_rdf_data VALUES ( 
SDO_RDF_TRIPLE_S('family', 
'<http://www.example.org/family/John>', 
'<http://www.example.org/family/fatherOf>', 
'<http://www.example.org/family/Matt>'));
 
-- Janice is the mother of Suzie.
INSERT INTO family_rdf_data VALUES ( 
SDO_RDF_TRIPLE_S('family', 
'<http://www.example.org/family/Janice>', 
'<http://www.example.org/family/motherOf>', 
'<http://www.example.org/family/Suzie>'));
 
-- Janice is the mother of Matt.
INSERT INTO family_rdf_data VALUES ( 
SDO_RDF_TRIPLE_S('family', 
'<http://www.example.org/family/Janice>', 
'<http://www.example.org/family/motherOf>', 
'<http://www.example.org/family/Matt>'));
 
-- Sammy is the father of Cathy.
INSERT INTO family_rdf_data VALUES ( 
SDO_RDF_TRIPLE_S('family', 
'<http://www.example.org/family/Sammy>', 
'<http://www.example.org/family/fatherOf>', 
'<http://www.example.org/family/Cathy>'));
 
-- Sammy is the father of Jack.
INSERT INTO family_rdf_data VALUES (
SDO_RDF_TRIPLE_S('family', 
'<http://www.example.org/family/Sammy>', 
'<http://www.example.org/family/fatherOf>', 
'<http://www.example.org/family/Jack>'));
 
-- Suzie is the mother of Cathy.
INSERT INTO family_rdf_data VALUES ( 
SDO_RDF_TRIPLE_S('family', 
'<http://www.example.org/family/Suzie>', 
'<http://www.example.org/family/motherOf>', 
'<http://www.example.org/family/Cathy>'));
 
-- Suzie is the mother of Jack.
INSERT INTO family_rdf_data VALUES ( 
SDO_RDF_TRIPLE_S('family', 
'<http://www.example.org/family/Suzie>', 
'<http://www.example.org/family/motherOf>', 
'<http://www.example.org/family/Jack>'));
 
-- Matt is the father of Tom.
INSERT INTO family_rdf_data VALUES ( 
SDO_RDF_TRIPLE_S('family', 
'<http://www.example.org/family/Matt>', 
'<http://www.example.org/family/fatherOf>', 
'<http://www.example.org/family/Tom>'));
 
-- Matt is the father of Cindy
INSERT INTO family_rdf_data VALUES ( 
SDO_RDF_TRIPLE_S('family', 
'<http://www.example.org/family/Matt>', 
'<http://www.example.org/family/fatherOf>', 
'<http://www.example.org/family/Cindy>'));
 
-- Martha is the mother of Tom.
INSERT INTO family_rdf_data VALUES ( 
SDO_RDF_TRIPLE_S('family', 
'<http://www.example.org/family/Martha>', 
'<http://www.example.org/family/motherOf>', 
'<http://www.example.org/family/Tom>'));
 
-- Martha is the mother of Cindy. 
INSERT INTO family_rdf_data VALUES ( 
SDO_RDF_TRIPLE_S('family', 
'<http://www.example.org/family/Martha>', 
'<http://www.example.org/family/motherOf>', 
'<http://www.example.org/family/Cindy>'));
 
-- Cathy is the sister of Jack.
INSERT INTO family_rdf_data VALUES ( 
SDO_RDF_TRIPLE_S('family', 
'<http://www.example.org/family/Cathy>', 
'<http://www.example.org/family/sisterOf>', 
'<http://www.example.org/family/Jack>'));
 
-- Jack is male.
INSERT INTO family_rdf_data VALUES ( 
SDO_RDF_TRIPLE_S('family', 
'<http://www.example.org/family/Jack>', 
'<http://www.w3.org/1999/02/22-rdf-syntax-ns#type>',
'<http://www.example.org/family/Male>'));
 
-- Tom is male.
INSERT INTO family_rdf_data VALUES ( 
SDO_RDF_TRIPLE_S('family', 
'<http://www.example.org/family/Tom>', 
'<http://www.w3.org/1999/02/22-rdf-syntax-ns#type>',
'<http://www.example.org/family/Male>'));
 
-- Cindy is female.
INSERT INTO family_rdf_data VALUES ( 
SDO_RDF_TRIPLE_S('family', 
'<http://www.example.org/family/Cindy>', 
'<http://www.w3.org/1999/02/22-rdf-syntax-ns#type>',
'<http://www.example.org/family/Female>'));
 
-- Person is a class.
INSERT INTO family_rdf_data VALUES ( 
SDO_RDF_TRIPLE_S('family', 
'<http://www.example.org/family/Person>', 
'<http://www.w3.org/1999/02/22-rdf-syntax-ns#type>',
'<http://www.w3.org/2000/01/rdf-schema#Class>'));
 
-- Male is a subclass of Person.
INSERT INTO family_rdf_data VALUES ( 
SDO_RDF_TRIPLE_S('family', 
'<http://www.example.org/family/Male>', 
'<http://www.w3.org/2000/01/rdf-schema#subClassOf>',
'<http://www.example.org/family/Person>'));
 
-- Female is a subclass of Person. 
INSERT INTO family_rdf_data VALUES ( 
SDO_RDF_TRIPLE_S('family', 
'<http://www.example.org/family/Female>', 
'<http://www.w3.org/2000/01/rdf-schema#subClassOf>',
'<http://www.example.org/family/Person>'));
 
-- siblingOf is a property.
INSERT INTO family_rdf_data VALUES ( 
SDO_RDF_TRIPLE_S('family', 
'<http://www.example.org/family/siblingOf>', 
'<http://www.w3.org/1999/02/22-rdf-syntax-ns#type>',
'<http://www.w3.org/1999/02/22-rdf-syntax-ns#Property>'));
 
-- parentOf is a property.
INSERT INTO family_rdf_data VALUES ( 
SDO_RDF_TRIPLE_S('family', 
'<http://www.example.org/family/parentOf>', 
'<http://www.w3.org/1999/02/22-rdf-syntax-ns#type>',
'<http://www.w3.org/1999/02/22-rdf-syntax-ns#Property>'));
 
-- brotherOf is a subproperty of siblingOf.
INSERT INTO family_rdf_data VALUES ( 
SDO_RDF_TRIPLE_S('family', 
'<http://www.example.org/family/brotherOf>', 
'<http://www.w3.org/2000/01/rdf-schema#subPropertyOf>',
'<http://www.example.org/family/siblingOf>'));
 
-- sisterOf is a subproperty of siblingOf.
INSERT INTO family_rdf_data VALUES ( 
SDO_RDF_TRIPLE_S('family', 
'<http://www.example.org/family/sisterOf>', 
'<http://www.w3.org/2000/01/rdf-schema#subPropertyOf>',
'<http://www.example.org/family/siblingOf>'));
 
-- A brother is male.
INSERT INTO family_rdf_data VALUES ( 
SDO_RDF_TRIPLE_S('family', 
'<http://www.example.org/family/brotherOf>', 
'<http://www.w3.org/2000/01/rdf-schema#domain>',
'<http://www.example.org/family/Male>'));
 
-- A sister is female.
INSERT INTO family_rdf_data VALUES ( 
SDO_RDF_TRIPLE_S('family', 
'<http://www.example.org/family/sisterOf>', 
'<http://www.w3.org/2000/01/rdf-schema#domain>',
'<http://www.example.org/family/Female>'));
 
-- fatherOf is a subproperty of parentOf.
INSERT INTO family_rdf_data VALUES ( 
SDO_RDF_TRIPLE_S('family', 
'<http://www.example.org/family/fatherOf>', 
'<http://www.w3.org/2000/01/rdf-schema#subPropertyOf>',
'<http://www.example.org/family/parentOf>'));
 
-- motherOf is a subproperty of parentOf.
INSERT INTO family_rdf_data VALUES ( 
SDO_RDF_TRIPLE_S('family', 
'<http://www.example.org/family/motherOf>', 
'<http://www.w3.org/2000/01/rdf-schema#subPropertyOf>',
'<http://www.example.org/family/parentOf>'));
 
-- A father is male.
INSERT INTO family_rdf_data VALUES ( 
SDO_RDF_TRIPLE_S('family', 
'<http://www.example.org/family/fatherOf>', 
'<http://www.w3.org/2000/01/rdf-schema#domain>',
'<http://www.example.org/family/Male>'));
 
-- A mother is female.
INSERT INTO family_rdf_data VALUES ( 
SDO_RDF_TRIPLE_S('family', 
'<http://www.example.org/family/motherOf>', 
'<http://www.w3.org/2000/01/rdf-schema#domain>',
'<http://www.example.org/family/Female>'));
 
-- Use SET ESCAPE OFF to prevent the caret (^) from being
-- interpreted as an escape character. Two carets (^^) are
-- used to represent typed literals.
SET ESCAPE OFF;
 
-- Cathy's height is 5.8 (decimal).
INSERT INTO family_rdf_data VALUES (
SDO_RDF_TRIPLE_S('family', 
'<http://www.example.org/family/Cathy>', 
'<http://www.example.org/family/height>',
'"5.8"^^xsd:decimal'));
 
-- Jack's height is 6 (integer).
INSERT INTO family_rdf_data VALUES (
SDO_RDF_TRIPLE_S('family', 
'<http://www.example.org/family/Jack>', 
'<http://www.example.org/family/height>',
'"6"^^xsd:integer'));
 
-- Tom's height is 05.75 (decimal).
INSERT INTO family_rdf_data VALUES (
SDO_RDF_TRIPLE_S('family', 
'<http://www.example.org/family/Tom>', 
'<http://www.example.org/family/height>',
'"05.75"^^xsd:decimal'));
 
-- Cindy's height is 06.00 (decimal).
INSERT INTO family_rdf_data VALUES (
SDO_RDF_TRIPLE_S('family', 
'<http://www.example.org/family/Cindy>', 
'<http://www.example.org/family/height>',
'"06.00"^^xsd:decimal'));
 
COMMIT;
 
-- RDFS inferencing in the family model
BEGIN
  SEM_APIS.CREATE_ENTAILMENT(
    'rdfs_rix_family',
    SEM_Models('family'),
    SEM_Rulebases('RDFS'));
END;
/
 
-- Select all males from the family model, without inferencing.
-- (Returns only Jack and Tom.)
SELECT m
  FROM TABLE(SEM_MATCH(
    '{?m rdf:type :Male}',
    SEM_Models('family'),
    null,
    SEM_ALIASES(SEM_ALIAS('','http://www.example.org/family/')),
    null));
 
-- Select all males from the family model, with RDFS inferencing.
-- (Returns Jack, Tom, John, Sammy, and Matt.)
SELECT m
  FROM TABLE(SEM_MATCH(
    '{?m rdf:type :Male}',
    SEM_Models('family'),
    SDO_RDF_Rulebases('RDFS'), 
    SEM_ALIASES(SEM_ALIAS('','http://www.example.org/family/')),
    null));
 
-- General inferencing in the family model
 
EXECUTE SEM_APIS.CREATE_RULEBASE('family_rb');
 
INSERT INTO mdsys.semr_family_rb VALUES(
  'grandparent_rule',
  '(?x :parentOf ?y) (?y :parentOf ?z)',
  NULL,
  '(?x :grandParentOf ?z)', 
  SEM_ALIASES(SEM_ALIAS('','http://www.example.org/family/')));
 
COMMIT;
 
-- Because a new rulebase has been created, and it will be used in the
-- entailment, drop the preceding entailment and then re-create it.
EXECUTE SEM_APIS.DROP_ENTAILMENT ('rdfs_rix_family');
 
-- Re-create the entailment.
BEGIN
  SEM_APIS.CREATE_ENTAILMENT(
    'rdfs_rix_family',
    SEM_Models('family'),
    SEM_Rulebases('RDFS','family_rb'));
END;
/
 
-- Select all grandfathers and their grandchildren from the family model, 
-- without inferencing. (With no inferencing, no results are returned.)
SELECT x grandfather, y grandchild
  FROM TABLE(SEM_MATCH(
    '{?x :grandParentOf ?y . ?x rdf:type :Male}',
    SEM_Models('family'),
    null, 
    SEM_ALIASES(SEM_ALIAS('','http://www.example.org/family/')),
    null));
 
-- Select all grandfathers and their grandchildren from the family model.
-- Use inferencing from both the RDFS and family_rb rulebases.
SELECT x grandfather, y grandchild
  FROM TABLE(SEM_MATCH(
    '{?x :grandParentOf ?y . ?x rdf:type :Male}',
    SEM_Models('family'),
    SEM_Rulebases('RDFS','family_rb'), 
    SEM_ALIASES(SEM_ALIAS('','http://www.example.org/family/')),
    null));
 
-- Set up to find grandfathers of tall (>= 6) grandchildren
-- from the family model, with RDFS inferencing and
-- inferencing using the "family_rb" rulebase.
 
UPDATE mdsys.semr_family_rb SET
  antecedents = '(?x :parentOf ?y) (?y :parentOf ?z) (?z :height ?h)',
  filter = '(h >= ''6'')',
  aliases = SEM_ALIASES(SEM_ALIAS('','http://www.example.org/family/'))
WHERE rule_name = 'GRANDPARENT_RULE';
 
-- Because the rulebase has been updated, drop the preceding entailment, 
-- and then re-create it.
EXECUTE SEM_APIS.DROP_ENTAILMENT ('rdfs_rix_family');
 
-- Re-create the entailment.
BEGIN
  SEM_APIS.CREATE_ENTAILMENT(
    'rdfs_rix_family',
    SEM_Models('family'),
    SEM_Rulebases('RDFS','family_rb'));
END;
/
 
-- Find the entailment that was just created (that is, the
-- one based on the specified model and rulebases).
SELECT SEM_APIS.LOOKUP_ENTAILMENT(SEM_MODELS('family'),
  SEM_RULEBASES('RDFS','family_rb')) AS lookup_entailment FROM DUAL;
 
-- Select grandfathers of tall (>= 6) grandchildren, and their
-- tall grandchildren.
SELECT x grandfather, y grandchild
  FROM TABLE(SEM_MATCH(
    '{?x :grandParentOf ?y . ?x rdf:type :Male}',
    SEM_Models('family'),
    SEM_RuleBases('RDFS','family_rb'), 
    SEM_ALIASES(SEM_ALIAS('','http://www.example.org/family/')), 
    null));

1.16 リリース11.1以降のソフトウェアでの名称変更

Oracle Databaseリリース11.1では、セマンティク・データのサポートが元のRDFの対象範囲を超えて拡張されているため、多くのソフトウェア・オブジェクト(PL/SQLパッケージ、関数およびプロシージャ、システム表およびビューなど)の名前が変更されています。

ほとんどの場合、この変更で文字列RDFSEMに置換されていますが、SDO_RDFSEMに置換されている場合もあります。

リリース11.1より前の名前を使用しているすべての有効なコードは、引き続き動作します。既存のアプリケーションに障害は発生しません。ただし、古いアプリケーションは変更して新しいオブジェクト名を使用することをお薦めします。新規アプリケーションでは新しい名前を使用してください。このマニュアルでは、新しい名前のみを記載しています。

表1-20に、セマンティク・テクノロジのサポートに関連する一部のオブジェクトの旧名と新規名を、旧名のアルファベット順に示します。

表1-20 セマンティク・テクノロジのソフトウェア・オブジェクト: 旧名と新規名

旧名称 新名称

RDF_ALIASデータ型

SEM_ALIAS

RDF_MODEL$ビュー

SEM_MODEL$

RDF_RULEBASE_INFOビュー

SEM_RULEBASE_INFO

RDF_RULES_INDEX_DATASETSビュー

SEM_RULES_INDEX_DATASETS

RDF_RULES_INDEX_INFOビュー

SEM_RULES_INDEX_INFO

RDFI_rules-index-nameビュー

SEMI_rules-index-name

RDFM_model-nameビュー

SEMM_model-name

RDFR_rulebase-nameビュー

SEMR_rulebase-name

SDO_RDFパッケージ

SEM_APIS

SDO_RDF_INFERENCEパッケージ

SEM_APIS

SDO_RDF_MATCH表関数

SEM_MATCH

SDO_RDF_MODELSデータ型

SEM_MODELS

SDO_RDF_RULEBASESデータ型

SEM_RULEBASES

1.17 RDFセマンティク・グラフの詳細

RDFセマンティク・グラフ・サポートの詳細が用意されています。

次の資料も参照してください。

1.18 リリース12.2よりも前のセマンティク・データに必要な移行作業

Oracle Database 11.1、11.2または12.1で作成されたセマンティク・データがある場合、そのデータをOracle Database 12.2の環境で使用するには、データの移行が必要です。

移行を行うには、SEM_APIS.MIGRATE_DATA_TO_CURRENTプロシージャを使用します。このプロシージャは、既存のセマンティク・データに適用されるだけでなく、環境に導入されているその他のあらゆるセマンティク・データに対しても、そのデータがOracle Database 11.1、11.2または12.1で作成されている場合、適用されます。

こうする必要があるのは、ORDER BYを使用する問合せのパフォーマンスを最適なものにするためです。リリース12.2では、Oracle Databaseによって、RDF_VALUE$表(「文」を参照)のORDER_TYPE列、ORDER_NUM列およびORDER_DATE列(リリース12.2で追加)が作成され、値が格納され、使用されます。SEM_APIS.MIGRATE_DATA_TO_CURRENTプロシージャにより、こうした並べ替えに関連する列に値が格納されます。これが実行されない場合、既存のデータに対してこうした列の値はNULLになります。

このプロシージャを、Oracle Databaseリリース12.2へアップグレードした後に実行します。以前のリリースを使用して作成したセマンティク・データを、リリース12.2の環境へ後から取り込む場合にも、データの使用前にこのプロシージャを実行する必要があります。セマンティク・データの量が多い場合、プロシージャの実行に長時間を要することがあるため、実行のタイミングを決める際にはその点を考慮する必要があります。(なお、大規模なデータ・セットでは、INS_AS_SEL=Tオプションを使用することで、SEM_APIS.MIGRATE_DATA_TO_CURRENTプロシージャのパフォーマンスが向上します。)