2 カーレース二面性ビューの例の概要
F1カーレースのデータは、JSONリレーショナル二面性ビューの機能を示すためにこのドキュメントで使用されます。
3種類のJSONドキュメント(ドライバ、レース、チーム)を使用するドキュメント中心のアプリケーションを考えます。これらの種類のドキュメントのそれぞれは、データを別の種類と共有しています。次に例を示します。
-
ドライバ・ドキュメントには、ドライバに関する情報、ドライバのチームの識別情報およびドライバが参加したレースに関する情報が含まれています。
-
レース・ドキュメントには、特定のレースに関する情報に、表彰者(1位、2位、3位の勝者)に関する情報および各ドライバのレースでの結果が含まれています。これらのいずれにも、ドライバ名とチーム名が含まれています。レーシング・データは1シーズンのレース用です。
-
チーム・ドキュメントには、チームに関する情報に、チームのドライバに関する情報が含まれています。
このデータに対してアプリケーションが実行する操作には、次のものがあります。
-
データベースに対するドライバ、レースまたはチームの追加または削除
-
ドライバ、レースまたはチームの情報の更新
-
チームへのドライバの追加、チームからのドライバの削除、またはチーム間でのドライバの移動
-
ドライバおよびレース情報へのレース結果の追加
この例の目的は、すべての共通情報を共有することです。つまり、ドライバ二面性ビューのID番号302のドライバは、チーム・ビューのドライバ番号302と同じです。
2つの二面性ビュー間で共通のデータの共有を指定するには、それらの間の関係を定義します。これは、二面性ビューの基礎となる表の主キーと外部キーの指定によって実行します。
特定の二面性ビューを定義すると、ビューでサポートされるドキュメントへの挿入、削除または更新が可能かどうか、それらの制約のオーバーライド、サポートされているドキュメントでの特定のフィールドの挿入、削除または更新が可能かどうかを制御できます。デフォルトでは、二面性ビューは読取り専用です。ドキュメントの挿入、削除または更新は実行できません。
- カーレースの例、JSONドキュメント
カーレースの例には、3種類のドキュメント(チーム・ドキュメント、ドライバ・ドキュメントおよびレース・ドキュメント)があります。 - カーレースの例、エンティティの関係
ドライバ、カーレースおよびチーム・エンティティが、それらの間の関係とともに提示されます。アプリケーションの二面性ビューの定義に必要な表の決定に役立つように、アプリケーション・ドキュメントに対応するエンティティを定義します。 - カーレースの例、表
正規化されたエンティティは、データベース表としてモデル化されます。エンティティ関係は、主キー列と外部キー列間のリンク(制約)としてモデル化されます。表team
、driver
およびrace
は、カーレース・アプリケーションで使用されるチーム、ドライバおよびレースJSONドキュメントを提供およびサポートする二面性ビューを実装するために使用されます。 - カーレースの例、二面性ビュー
チーム、ドライバおよびレースの二面性ビューでは、カーレース・アプリケーションで使用されるチーム、ドライバおよびレースのJSONドキュメントが提供およびサポートされています。
関連項目:
-
SQLの使用によるJSONリレーショナル二面性ビューの操作。このドキュメント内の例を反映するSQLスクリプトです
2.1 カーレースの例、JSONドキュメント
カーレースの例には、3種類のドキュメント(チーム・ドキュメント、ドライバ・ドキュメントおよびレース・ドキュメント)があります。
二面性ビューでサポートされるドキュメントには、常に上位(ルート)レベルにドキュメント識別子フィールド_id
が含まれます。これは、ビューの基礎となる表の主キー列に対応します。「二面性ビューのドキュメント識別子フィールド」を参照してください。(カーレースの例では、このような各表に1つの主キー列があります。)
このドキュメントでは、次の命名規則に従います:
-
各種類のドキュメント(チーム、ドライバまたはレース)のドキュメント識別子フィールド(
_id
)は、それらのドキュメントをサポートする二面性ビューのルート表の主キー列に対応します。たとえば、チーム・ドキュメントのフィールド_id
は、表team
の主キー列team_id
に対応します。これは、二面性ビューteam_dv
の基礎となるルート表です。 -
1つの二面性ビュー(
team_dv
など)でサポートされている1種類のドキュメント(チームなど)には、...Id
という名前の他のフィールド(driverId
など)を含めることができます。このフィールドは、他の二面性ビューの基礎となる表の主キー列への外部キー参照(共有されるデータを含む列)を表します。たとえば、チーム・ドキュメントの場合、フィールドdriverId
は、ドライバ・ドキュメントのドキュメント識別子フィールド(_id
)を参照する外部キーを表します。
ノート:
ここでは、アプリケーション・ロジックのドキュメント・コンテンツまたは各ドキュメントのペイロードのみを示します。つまり、ここに示すドキュメントには、自動生成および管理される上位レベルのフィールド_metadata
(値がフィールドetag
およびasof
を持つオブジェクト)は含まれていません。ただし、このドキュメント処理フィールドは、二面性ビューでサポートされるドキュメントに常に含まれます。フィールド_metadata
の詳細は、「カーレースの例、二面性ビュー」を参照してください。
例2-1 チーム・ドキュメント
チーム・ドキュメントには、チームに関連する情報に加えて、チームのドライバに関する情報が含まれていますが、必ずしもそのドライバに関連しているわけではありません。
-
上位レベルのフィールド
_id
は、チーム・ドキュメントを一意に識別します。これは、ドキュメント識別子フィールドです。表team
の列team_id
はこのフィールドに対応しており、表の主キーです。 -
ドライバ・ドキュメントと共有されないチーム情報は、フィールド
_id
および上位レベルのフィールドname
およびpoints
にあります。 -
ドライバ・ドキュメントと共有されるチーム情報は、フィールド
driver
のdriverId
、name
およびpoints
フィールドにあります。フィールドdriverId
の値は、ドライバ・ドキュメントのドキュメント識別子フィールド(_id
)の値です。
{"_id" : 302,
"name" : "Ferrari",
"points" : 300,
"driver" : [ {"driverId" : 103,
"name" : "Charles Leclerc",
"points" : 192},
{"driverId" : 104,
"name" : "Carlos Sainz Jr",
"points" : 118} ]}
例2-2 ドライバ・ドキュメント
ドライバ・ドキュメントには、ドライバに関連する情報に加えて、ドライバのチームの識別情報およびドライバが参加したレースに関する情報が含まれていますが、必ずしも、そのチームまたはレースに関連しているわけではありません。
-
上位レベルのフィールド
_id
は、ドライバ・ドキュメントを一意に識別します。これは、ドキュメント識別子フィールドです。driver
表の列driver_id
はこのフィールドに対応しており、表の主キーです。 -
レースまたはチーム・ドキュメントと共有されないドライバ情報は、フィールド
_id
、name
およびpoints
にあります。 -
レース・ドキュメントと共有されるドライバ情報は、フィールド
race
にあります。フィールドraceId
の値は、レース・ドキュメントのドキュメント識別子フィールド(_id
)の値です。 -
チーム・ドキュメントと共有されるドライバ情報は、
teamId
などのフィールドにあり、その値はチーム・ドキュメントのドキュメント識別子フィールド(_id
)の値です。
2つの代替バージョンのドライバ・ドキュメントが表示されますが、ネストされたチームおよびレース情報がある場合とない場合があります。
ネストしたチームおよびレース情報があるドライバ・ドキュメント:
フィールドteamInfo
には、ネストされたチーム情報(フィールドteamId
およびname
)が含まれています。フィールドraceInfo
には、ネストされたレース情報(フィールドraceId
およびname
)が含まれています。
{"_id" : 101,
"name" : "Max Verstappen",
"points" : 258,
"teamInfo" : {"teamId" : 301, "name" : "Red Bull"},
"race" : [ {"driverRaceMapId" : 3,
"raceInfo" : {"raceId" : 201,
"name" : "Bahrain Grand Prix"},
"finalPosition" : 19},
{"driverRaceMapId" : 11,
"raceInfo" : {"raceId" : 202,
"name" : "Saudi Arabian Grand Prix"},
"finalPosition" : 1} ]}
ネストしたチームおよびレース情報がないドライバ・ドキュメント:
フィールドteamId
およびteam
は、teamInfo
オブジェクトにネストされていません。フィールドraceId
およびname
は、raceInfo
オブジェクトにネストされていません。
{"_id" : 101,
"name" : "Max Verstappen",
"points" : 25,
"teamId" : 301,
"team" : "Red Bull",
"race" : [ {"driverRaceMapId" : 3,
"raceId" : 201,
"name" : "Bahrain Grand Prix",
"finalPosition" : 19},
{"driverRaceMapId" : 11,
"raceId" : 202,
"name" : "Saudi Arabian Grand Prix",
"finalPosition" : 1} ]}
例2-3 カーレース・ドキュメント
レース・ドキュメントには、特定のレースに関する情報に、表彰者(1位、2位、3位)に関する情報および各ドライバのレースでの結果が含まれています。表彰者には、ドライバ名とチーム名が含まれています。各ドライバの結果には、ドライバの名前が含まれています。
これらの両方には、ドライバ名とチーム名が含まれています。
-
上位レベルのフィールド
_id
は、レース・ドキュメントを一意に識別します。これは、ドキュメント識別子フィールドです。race
表の列race_id
はこのフィールドに対応しており、表の主キーです。 -
ドライバまたはチーム・ドキュメントと共有されないレース情報は、フィールド
_id
、name
(上位レベル)、laps
、date
、time
およびposition
にあります。 -
ドライバ・ドキュメントと共有されるレース情報は、
driverId
などのフィールドにあり、その値はドライバ・ドキュメントのドキュメント識別子フィールド(_id
)の値です。 -
チーム・ドキュメントと共有されるレース情報は、フィールド
team
(podium
の下にあるwinner
、firstRunnerUp
およびsecondRunnerUp
の下)にあります。
2つの代替バージョンのレース・ドキュメントが表示されますが、ネストされたドライバ情報がある場合とない場合があります。
ネストしたドライバ情報があるレース・ドキュメント:
{"_id" : 201,
"name" : "Bahrain Grand Prix",
"laps" : 57,
"date" : "2022-03-20T00:00:00",
"podium" : {"winner" : {"name" : "Charles Leclerc",
"team" : "Ferrari",
"time" : "02:00:05.3476"},
"firstRunnerUp" : {"name" : "Carlos Sainz Jr",
"team" : "Ferrari",
"time" : "02:00:15.1356"},
"secondRunnerUp" : {"name" : "Max Verstappen",
"team" : "Red Bull",
"time" : "02:01:01.9253"}},
"result" : [ {"driverRaceMapId" : 3,
"position" : 1,
"driverInfo" : {"driverId" : 103,
"name" : "Charles Leclerc"},
{"driverRaceMapId" : 4,
"position" : 2,
"driverInfo" : {"driverId" : 104,
"name" : "Carlos Sainz Jr"},
{"driverRaceMapId" : 9,
"position" : 3,
"driverInfo" : {"driverId" : 101,
"name" : "Max Verstappen"},
{"driverRaceMapId" : 10,
"position" : 4,
"driverInfo" : {"driverId" : 102,
"name" : "Sergio Perez"} ]}
ネストしたドライバ情報がないレース・ドキュメント:
{"_id" : 201,
"name" : "Bahrain Grand Prix",
"laps" : 57,
"date" : "2022-03-20T00:00:00",
"podium" : {"winner" : {"name" : "Charles Leclerc",
"team" : "Ferrari",
"time" : "02:00:05.3476"},
"firstRunnerUp" : {"name" : "Carlos Sainz Jr",
"team" : "Ferrari",
"time" : "02:00:15.1356"},
"secondRunnerUp" : {"name" : "Max Verstappen",
"team" : "Red Bull",
"time" : "02:01:01.9253"}},
"result" : [ {"driverRaceMapId" : 3,
"position" : 1,
"driverId" : 103,
"name" : "Charles Leclerc"},
{"driverRaceMapId" : 4,
"position" : 2,
"driverId" : 104,
"name" : "Carlos Sainz Jr"},
{"driverRaceMapId" : 9,
"position" : 3,
"driverId" : 101,
"name" : "Max Verstappen"},
{"driverRaceMapId" : 10,
"position" : 4,
"driverId" : 102,
"name" : "Sergio Perez"} ]}
関連トピック
親トピック: カーレース二面性ビューの例の概要
2.2 カーレースの例、エンティティ関係
ドライバ、カーレースおよびチーム・エンティティが、それらの間の関係とともに提示されます。アプリケーションの二面性ビューの定義に必要な表の決定に役立つように、アプリケーション・ドキュメントに対応するエンティティを定義します。
アプリケーションで使用するドキュメントから、エンティティとその関係を設定できます。各エンティティが対応しているドキュメント・タイプは、ドライバ、レース、チームです。
対応するドキュメントと異なり、使用するエンティティはコンテンツの重複がなく、正規化されています。エンティティのコンテンツ(エンティティが表す内容)は、対応するドキュメント・タイプのみに固有であり、別のドキュメント・タイプの一部であるものは含まれていません。
-
ドライバ・エンティティは、レース・ドキュメントまたはチーム・ドキュメントにないドライバ・ドキュメントのコンテンツのみを表します。これには、ドキュメント・フィールド
name
およびpoints
に対応するドライバの名前およびポイントのみが含まれています。 -
レース・エンティティは、ドライバ・ドキュメントまたはチーム・ドキュメントにないレース・ドキュメントのコンテンツのみを表します。これには、ドキュメント・フィールド
name
、laps
、date
およびpodium
に対応するレースの名前、ラップ数、日付および表彰者情報のみが含まれています。 -
チーム・エンティティは、ドキュメントまたはレース・ドキュメントにないチーム・ドキュメントのコンテンツのみを表します。これには、ドキュメント・フィールド
name
およびpoints
に対応するチームの名前およびポイントのみが含まれています。
2つのエンティティは、カーディナリティに従って関連しています。このような関係には次の3つのタイプがあります: 脚注1
- 1対1 (1: 1)
- エンティティAのインスタンスは、エンティティBの1つのインスタンスにのみ関連付けることができます。たとえば、1人のドライバは1つのチームにのみ存在できます。
- 1対多(1: N)
- エンティティAのインスタンスは、エンティティBの1つ以上のインスタンスに関連付けることができます。たとえば、チームには多数のドライバを含めることができます。
- 多対多(N:N)
- エンティティAのインスタンスは、エンティティBの1つ以上のインスタンスに関連付けることができ、その逆も可能です。たとえば、レースには多くのドライバがあり、ドライバは多くのレースに参加できます。
多対1 (N:1)の関係は、反対の視点から見ると、1対多の関係にすぎません。1対多のみを使用します。
図2-1を参照してください。矢印は関係の方向を示し、矢印は2番目のカーディナリティを示します。たとえば、エンティティteamからエンティティdriverへの1:Nの矢印はdriverの方向を指し、1つのチームが多くのドライバに関連していることを示します。
ドライバは、1つのチームにのみ関連付けることができます(1:1)。チームは、複数のドライバに関連付けることができます(1:N)。ドライバは、複数のレースに関連付けることができます(N:N)。レースは、複数のドライバに関連付けることができます(N:N)。
2.3 カーレースの例、表
正規化されたエンティティは、データベース表としてモデル化されます。エンティティ関係は、主キー列と外部キー列間のリンク(制約)としてモデル化されます。表team
、driver
およびrace
は、カーレース・アプリケーションで使用されるチーム、ドライバおよびレースJSONドキュメントを提供およびサポートする二面性ビューを実装するために使用されます。
正規化されたエンティティでは、コンテンツは重複していません。ただし、別の表に格納されているコンテンツを参照する表として、論理的に重複させるためにエンティティを実装するデータベース表が必要です。これを実現するには、外部キー制約を使用して、他の表にリンクされている列を追加します。これは、共通のコンテンツの共有を実装する表間の外部キー関係です。
二面性ビューの定義に使用する表は、次の要件を満たす必要があります(それ以外の場合、ビューを作成しようとするとエラーが発生します)。
-
ビューの上位レベル(ルート)表には、表の行を一意に識別する1つ以上の列で構成される主キーが必要です。これにより、
NULL
値が可能な一意キーまたはNULL
列を持つ一意キーを使用するために起こる曖昧さが回避されます。主キー列の値は、サポートするように表が設計されているJSONドキュメントのドキュメント識別子フィールド(
_id
)の値に対応します(「二面性ビューのドキュメント識別子フィールド」を参照)。(カーレースの例で使用される各表の主キー列は、1つのみです。) -
二面性ビューの定義に使用される他の各表には、主キーまたは一意キーも必要です。一意キーは、表内の行を一意に識別する1つ以上の列のセットです。主キーがない場合は、一意キーの少なくとも1つの列を
NULL
にしないでください。 -
各主キーと各一意キーには、一意の索引が定義されている必要があります。各外部キー列にも索引を定義することをお薦めします。主キーと外部キー間の参照(リンク)を定義する必要がありますが、適用する必要はありません。
ノート:
1次索引および一意索引は通常、主キーおよび一意キー整合性制約を定義するときに暗黙的に作成されます。ただし、これは保証されておらず、索引の作成後に削除できます。必要な索引が存在することを確認する必要があります。『Oracle Database管理者ガイド』の索引の作成に関する項を参照してください。
一意キーと同様に、主キーおよび外部キーは、複数の列で構成されるコンポジットにできます。このドキュメントでは通常、これらは単一列のキーと呼びますが、キーが言及されるたびにこの可能性を念頭に置いてください。
一般に、外部キー列の値はNULL
でもかまいません。前述の要件以外に、外部キー列をNULL
値可能にしない場合は、表定義でNOT NULL
としてマークします。
カーレースの例では、チーム、ドライバおよびレースのエンティティは、表team
、driver
およびrace
によって実装され、次の列があります:
-
team
表:-
team_id
- 主キー -
name
- 一意キー -
points
-
-
driver
表:-
driver_id
- 主キー -
name
- 一意キー -
points
-
team_id
- 表team
の列team_id
にリンクする外部キー
-
-
race
表:-
race_id
- 主キー -
name
- 一意キー(そのため、表には重複行がありません。同じ名前で2つのレースは存在できません) -
laps
-
race_date
-
podium
-
カーレース・アプリケーションのロジックでは、特定のチーム名を持つ1つのチームのみ、特定のドライバ名を持つ1つのドライバのみ、および特定のレース名を持つ1つのレースのみが存在することが要求されるため、これらの各表のname
列は一意キーになります。(これは、特定のname
フィールド値を持つチーム・ドキュメントが1つのみで、特定のname
を持つドライバ・ドキュメントが1つのみで、特定のname
を持つレース・ドキュメントが1つのみであることを意味します。)
表driver
には、表team
と論理的に共有されるデータである追加列team_id
があります(チーム・ドキュメントのドキュメント識別子フィールド_id
に対応します)。この共有は、表team
の(主キー)列team_id
にリンクする表driver
の外部キーとして列を宣言することで定義されます。このリンクは、ドライバからチームへの1:1の関係と、チームからドライバへの1:Nの関係の両方を実装します。
しかし、他の共有、すなわち、レース・ドキュメントと共有されているドライバ・ドキュメント内のレース情報、およびドライバ・ドキュメントまたはチーム・ドキュメントと共有されているレース・ドキュメント内の情報についてはどうでしょうか。
この情報共有は、エンティティ・ドライバとレース間の多対多(N:N)関係に対応しています。データベースはN:N関係を直接実装しません。かわりに、マッピング表(または関連表)と呼ばれる別の表を追加して、表driver
とrace
間の関係の橋渡しをする必要があります。マッピング表には、外部キーとして、関連付けられている2つの表の主キー列が含まれています。
N:Nのエンティティ関係は、1:Nの関係と同等で、その後に1:1の関係が続きます。この等価性により、表driver
とrace
の間にマッピング表driver_race_map
を追加して、データベース表を使用したN:Nのエンティティ関係が実装されます。
図2-2は、図2-1と同等です。中間エンティティd-r-mapが追加され、各N:Nの関係が1:Nの関係に拡張され、その後に1:1の関係が続きます。 脚注2
マッピング表driver_race_map
は、中間エンティティd-r-mapを実装します。次のような列があります。
-
driver_race_map_id
- 主キー -
race_id
— (1)表race
の主キー列race_id
にリンクする外部キーと、(2)一意キー(そのため、表には重複行がありません。特定のレースに対して同じドライバに2つのエントリは存在できません) -
driver_id
- 表driver
の主キー列driver_id
にリンクする外部キー -
position
外部キー・リンクおよび主キー・リンクで定義された関係とともに、カーレース表は依存関係グラフを形成します。図2-3に、これを示します。
例2-4 カーレース表の作成
この例では、各表を1つの主キー列を含めて作成します。その値は一連の整数として自動的に生成され、一意キー列name
も生成されます。これにより、主キー列に一意索引も暗黙的に作成されます。この例では、外部キー索引も作成します。
表race
の列podium
のデータ型はJSON
です。その内容は柔軟性があり、特定の構造やフィールド・タイプに準拠する必要はありません。あるいは、そのコンテンツを特定のJSONスキーマに準拠(つまり検証)するようにもできます。
CREATE TABLE team
(team_id INTEGER GENERATED BY DEFAULT ON NULL AS IDENTITY,
name VARCHAR2(255) NOT NULL UNIQUE,
points INTEGER NOT NULL,
CONSTRAINT team_pk PRIMARY KEY(team_id));
CREATE TABLE driver
(driver_id INTEGER GENERATED BY DEFAULT ON NULL AS IDENTITY,
name VARCHAR2(255) NOT NULL UNIQUE,
points INTEGER NOT NULL,
team_id INTEGER,
CONSTRAINT driver_pk PRIMARY KEY(driver_id),
CONSTRAINT driver_fk FOREIGN KEY(team_id) REFERENCES team(team_id));
CREATE TABLE race
(race_id INTEGER GENERATED BY DEFAULT ON NULL AS IDENTITY,
name VARCHAR2(255) NOT NULL UNIQUE,
laps INTEGER NOT NULL,
race_date DATE,
podium JSON,
CONSTRAINT race_pk PRIMARY KEY(race_id));
-- Mapping table, to bridge the tables DRIVER and RACE.
--
CREATE TABLE driver_race_map
(driver_race_map_id INTEGER GENERATED BY DEFAULT ON NULL AS IDENTITY,
race_id INTEGER NOT NULL,
driver_id INTEGER NOT NULL,
position INTEGER,
CONSTRAINT driver_race_map_uk UNIQUE (race_id, driver_id),
CONSTRAINT driver_race_map_pk PRIMARY KEY(driver_race_map_id),
CONSTRAINT driver_race_map_fk1 FOREIGN KEY(race_id)
REFERENCES race(race_id),
CONSTRAINT driver_race_map_fk2 FOREIGN KEY(driver_id)
REFERENCES driver(driver_id));
-- Create foreign-key indexes
--
CREATE INDEX driver_fk_idx ON driver (team_id);
CREATE INDEX driver_race_map_fk1_idx ON driver_race_map (race_id);
CREATE INDEX driver_race_map_fk2_idx ON driver_race_map (driver_id);
ノート:
主キー、一意キーおよび外部キー整合性制約は、二面性ビューの基礎となる表に対して定義する必要があります(そうしないと、エラーが発生します)が、これらは強制する必要はありません。
場合によっては、特定の制約の条件を満たしていることがわかっているため、その制約を検証または強制する必要はありません。ただし、問合せのパフォーマンスを向上させるために制約が存在することが必要な場合もあります。その場合、制約はRELY
状態に設定できます。これは、その制約が満たされていると考えられていることを示します。Oracle Databaseデータ・ウェアハウス・ガイドのデータ・ウェアハウスにおけるRELY制約に関する項を参照してください。
外部キー制約をDEFERRABLE
にすることもできます。これは、トランザクションの最後に妥当性チェックが実行されるということです。『Oracle Database概要』の遅延可能制約を参照してください
ノート:
二面性ビューの基礎となる表の列で使用できるSQLデータ型は、次のとおりです: JSON
、BLOB
、CLOB
、NCLOB
、VARCHAR2
、NVARCHAR2
、CHAR
、NCHAR
、RAW
、BOOLEAN
、DATE
、TIMESTAMP
、TIMESTAMP WITH TIME ZONE
、INTERVAL YEAR TO MONTH
、INTERVAL DAY TO SECOND
、NUMBER
、BINARY_DOUBLE
およびBINARY_FLOAT
。他の列データ型を指定すると、エラーが発生します。
関連トピック
関連項目:
-
『Oracle Database JSON開発者ガイド』のJSONスキーマに関する項
-
JSONを使用したフレックスフィールドの実装(ビデオ、24分)
-
『Oracle Database SQL言語リファレンス』の「CREATE TABLE」
親トピック: カーレース二面性ビューの例の概要
2.4 カーレースの例、二面性ビュー
チーム、ドライバおよびレースの二面性ビューでは、カーレース・アプリケーションで使用されるチーム、ドライバおよびレースのJSONドキュメントが提供およびサポートされています。
ビューは、関連表driver
、race
およびteam
のデータの他、マッピング表driver_race_map
に基づいています。関連表はそれぞれビューdriver_dv
、race_dv
およびteam_dv
の基礎となっており、マッピング表はビューdriver_dv
およびrace_dv
の基礎となっています。
二面性ビューでは、JSONドキュメントをサポートしています。各ドキュメントには上位レベルのJSONオブジェクトがあります。二面性ビューは、JSON
データ型の単一列を持つ表の場合と同様に操作できます。
二面性ビューとそれに対応する上位レベルのJSONオブジェクトは、ネストされたSQL副問合せを使用してビュー定義に定義されているJSONオブジェクトおよび配列の階層を提供します。副問合せから収集されたデータは、親の主キーまたは一意キーと、子副問合せのWHERE
句の外部キーとの関係によって、親副問合せまたはルート表から収集されたデータと結合されます。
二面性ビューを作成せずに、SQL/JSON生成ファンクションを直接使用して通常の読取り専用SQLビューを作成できます(『Oracle Database JSON開発者ガイド』のJSON生成に基づいた読取り専用ビューを参照)。
二面性ビューは、制限された構造を持つJSON生成ビューであり、アプリケーションがビューを更新できるように明示的に設計されているため、基礎となる表を自動的に更新できます。すべての二面性ビューは、読取り専用であるビューも含め、これを許可するのと同じ制限を共有します。
ノート:
SQL/JSON生成ファンクションに対するCLOB
およびBLOB
データ型の入力の場合は、空のインスタンスがSQLのNULL
と区別されます。空のJSON文字列(""
)が生成されます。ただし、データ型VARCHAR2
、NVARCHAR2
およびRAW
の入力の場合、Oracle SQLでは空の値(長さがゼロ)をNULL
として扱うため、そのような値がJSON文字列に生成されると想定しないでください。
二面性ビューを基礎とする表のデータの列は、SQL/JSON生成ファンクションの入力として使用され、ビューでサポートされるJSONドキュメントを生成します。したがって、列の値が空の場合は、列のデータ型に応じて、空の文字列またはSQL NULL
値になります。
二面性ビューには、基礎となる表データから生成されるJSON
データ型のpayload列が1つのみ(DATA
)あります。したがって、二面性ビューの各行には、ビュー定義の上位レベルのオブジェクトである単一のJSONオブジェクトが含まれています。このオブジェクトはビューによってサポートされているJSONドキュメントとして機能します。
ペイロード・ドキュメント・コンテンツ(つまり、アプリケーション・コンテンツそれ自体)に加えて、ドキュメントの上位オブジェクトには常に、自動的に生成および管理されるドキュメント処理フィールド_metadata
があります。その値は、次のフィールドを持つオブジェクトです:
-
etag
- 特定のバージョンのドキュメントの一意の識別子。16進文字の文字列です。この識別子は、ドキュメント・コンテンツ(ペイロード)、つまり、フィールド
_metadata
を除くすべてのドキュメント・フィールドのハッシュ値として構築されます。(より正確には、基礎となる列に暗黙的または明示的にCHECK
注釈が付けられている、つまりこれらの列がETAG値に関与しているすべてのフィールド。)このETAG値により、アプリケーションでは、ドキュメントの特定のバージョンのコンテンツが別のバージョンのコンテンツと同じかどうかを判断できます。これは、オプティミスティックな同時実行性の実装などに使用されます。「二面性ビューでのオプティミスティックな同時実行性制御の使用」を参照してください。
-
asof
— JSONドキュメントの最新のシステム変更番号(SCN)をJSON番号として指定します。これにより、ドキュメントが生成された時点で最後の論理ポイントが記録されます。SCNを使用して、特定のJSONドキュメントがデータベースから取得された正確な時点で他のデータベース・オブジェクト(二面性ビュー、表)を問い合せることができます。これにより、データベースの読取りにおける一貫性が確保されます。「JSONドキュメントのシステム変更番号(SCN)の使用」を参照してください
ペイロード列DATA
の他に、二面性ビューには、SQLからアクセスできる2つの非表示列も含まれています:
-
OBJECT_ETAG
- この16バイトのRAW
列には、列DATA
の現在の行のETAG値が保持されます。つまり、ドキュメント・メタデータ・フィールドetag
に使用されるデータが保持されます。 -
OBJECT_RESID
- この可変長のRAW
列には、列DATA
の現在の行のコンテンツであるドキュメントを一意に識別するオブジェクト識別子が保持されます。列値は、ルート表の主キー列の連結バイナリ・エンコーディングです。
SQLまたはGraphQL言語のサブセットを使用して、二面性ビューを作成できます。
- SQLを使用したカーレース二面性ビューの作成
カーレース・アプリケーション用のチーム、ドライバおよびレースの二面性ビューを、SQLを使用して作成します。 - GraphQLを使用したカーレース二面性ビューの作成
カーレース・アプリケーション用のチーム、ドライバおよびレースの二面性ビューを、GraphQLを使用して作成します。
関連トピック
関連項目:
-
『Oracle Database SQL言語リファレンス』のCREATE JSON RELATIONAL DUALITY VIEWに関する項
-
SQL/JSONファンクション
json_object
、json_array
およびjson_arrayagg
および構文JSON {
…}
およびJSON [
…]
の詳細は、『Oracle Database JSON開発者ガイド』のSQLを使用したJSONデータの生成に関する項を参照してください -
『Oracle Database JSON開発者ガイド』のJSONデータ型のコンストラクタに関する項を参照してください
-
『Oracle Database概要』の「システム変更番号(SCN)」
親トピック: カーレース二面性ビューの例の概要
2.4.1 SQLを使用したカーレース二面性ビューの作成
カーレース・アプリケーション用のチーム、ドライバおよびレースの二面性ビューを、SQLを使用して作成します。
カーレース二面性ビューを定義するここでのSQL文では、SQL/JSON生成ファンクションを使用してJSONオブジェクトおよび配列を作成(生成)するための短縮形として、JSON
型のコンストラクタ・ファンクションJSON
を使用する簡略化された構文を使用します。JSON {
…}
はファンクションjson_object
を使用するための単純な構文で、JSON [
…]
はファンクションjson_array
またはjson_arrayagg
を使用するための単純な構文です。
JSON {
…}
およびJSON [
…]
の構文は、他のこのような構文内に埋め込まれている場合に、{
…}
および[
…]
のように省略できます。これらは、包含するJSON生成ファンクションの一部であると認識されています。
生成ファンクションjson_object
の引数は、個々のJSONオブジェクト・メンバーの定義です。フィールド名(points
など)の後にコロン(:
)またはキーワードIS
が続き、その後に定義フィールド値(110
など)が続きます。つまり、'points' : 110
または'points' IS 110
となります。JSONフィールド名は一重引用符文字('
)で囲まれることに注意してください。
フィールド値の一部は、ビューの上位レベルの表(ビューdriver_dv
の表driver
(別名d
)、ビューrace_dv
の表race
(別名r
)、ビューteam_dv
の表team
(別名t
))から列値として直接定義されます。たとえば、ビューdriver_dv
の場合、'name' : d.name
では、driver
表の列name
の値としてフィールドname
の値を定義します。
その他のフィールド値は、他の表のいずれかからデータを選択する副問合せ(SELECT
...)を使用して定義されます。そのデータは暗黙的に結合され、ビュー・データが形成されます。
一部の副問合せでは、JSON {
…}
という構文を使用します。この構文では、中カッコ({
、}
)で囲まれた定義によって定義されたフィールドを使用してJSONオブジェクトを定義します。たとえば、JSON {'_id' : r.race_id, 'name' : r.name}
は、表r
(race
)から、列race_id
およびname
の値によってそれぞれ定義されたフィールド_id
およびname
を使用してJSONオブジェクトを定義します。
その他の副問合せでは、JSON [
…]
という構文を使用します。この構文では、副問合せが返す値を持つ要素のJSON配列を、返される順序で定義します。たとえば、[ SELECT JSON {…} FROM driver WHERE ... ]
は、指定されたWHERE
条件が保持される表driver
から要素を選択するJSON配列を定義します。
二面性ビューdriver_dv
およびrace_dv
には、マッピング表driver_race_map
の各ネスト・データがあります。これらの各ビューの2つのバージョンが定義され、そのうちの1つにはネストされたオブジェクトが含まれ、もう1つはキーワードUNNEST
を使用して定義され、ネストされたオブジェクトが直接そのフィールドを組み込むようにフラット化されます。ビューdriver_dv
の場合、ネストされたオブジェクトはフィールドteamInfo
の値です。ビューrace_dv
の場合、ネストされたオブジェクトはフィールドdriverInfo
の値です。(必要に応じて、キーワードNEST
を使用して、ネストのデフォルト動作を明示的に指定できます。)
このドキュメントのほとんどのカーレースの例では、これらのネストされたオブジェクトなしでビューおよびドキュメント・バージョンを使用します。
ネストは、ルート表以外の表のフィールドに対するデフォルトの動作です。ネスト解除は、ルート表のフィールドに対するデフォルトの動作です。デフォルトの動作を明示的にする場合は、キーワードNEST
を使用します。例については、例7-1を参照してください。ルート表の主キー列に対応するフィールドはネストできません。ネストしようとするとエラーが発生します。
例2-5 SQLを使用した二面性ビューTEAM_DVの作成
この例では、チーム・オブジェクトが次のように表示される二面性ビューを作成します。チーム・オブジェクトには、値がチームのドライバを指定するネストされたオブジェクトの配列であるフィールドdriver
が含まれています。
{"_id" : 301, "name" : "Red Bull", "points" : 0, "driver" : [...]}
(作成されたビューは、例2-10のGraphQLを使用して作成されたビューと同じです。)
CREATE JSON RELATIONAL DUALITY VIEW team_dv AS
SELECT JSON {'_id' : t.team_id,
'name' : t.name,
'points' : t.points,
'driver' :
[ SELECT JSON {'driverId' : d.driver_id,
'name' : d.name,
'points' : d.points WITH NOCHECK}
FROM driver d WITH INSERT UPDATE
WHERE d.team_id = t.team_id ]}
FROM team t WITH INSERT UPDATE DELETE;
例2-6 SQLを使用した、ネストされたチーム情報での二面性ビューDRIVER_DVの作成
この例では、二面性ビューを作成し、ここでドライバ・オブジェクトは次のようになります。ドライバ・オブジェクトには、値がフィールドteamId
および(チーム) name
を持つネストされたオブジェクトであるフィールドteamInfo
が含まれています。
{"_id" : 101,
"name" : "Max Verstappen",
"points" : 0,
"teamInfo" : {"teamId" : 103, "name" : "Red Bull"},
"race" : [...]}
CREATE JSON RELATIONAL DUALITY VIEW driver_dv AS
SELECT JSON {'_id' : d.driver_id,
'name' : d.name,
'points' : d.points,
'teamInfo' :
(SELECT JSON {'teamId' : t.team_id,
'name' : t.name WITH NOCHECK}
FROM team t WITH NOINSERT NOUPDATE NODELETE
WHERE t.team_id = d.team_id),
'race' :
[ SELECT JSON {'driverRaceMapId' : drm.driver_race_map_id,
'raceInfo' :
(SELECT JSON {'raceId' : r.race_id,
'name' : r.name}
FROM race r WITH NOINSERT NOUPDATE NODELETE
WHERE r.race_id = drm.race_id),
'finalPosition' : drm.position}
FROM driver_race_map drm WITH INSERT UPDATE NODELETE
WHERE drm.driver_id = d.driver_id ]}
FROM driver d WITH INSERT UPDATE DELETE;
例2-7 SQLを使用した、ネストされていないチーム情報での二面性ビューDRIVER_DVの作成
この例では、二面性ビューを作成し、ここでドライバ・オブジェクトは次のようになります。ドライバ・オブジェクトには、値がフィールドteamId
およびname
を持つネストされたオブジェクトであるフィールドteamInfo
が含まれていません。かわりに、表teamのデータが上位レベルで取り込まれ、チーム名がフィールドteam
となります。
{"_id" : 101,
"name" : "Max Verstappen",
"points" : 0,
"teamId" : 103,
"team" : "Red Bull",
"race" : [...]}
'teamInfo' :
を使用して、表team
の副問合せから生成されるオブジェクト値で上位レベルのフィールドteamInfo
を定義するかわりに、ビュー定義はその副問合せの前にキーワードUNNEST
を付け、列name
のデータをフィールドteam
の値として使用します。その他の点では、このビュー定義は例2-6と同じです。
(作成されたビューは、例2-11のGraphQLを使用して作成されたビューと同じです。)
CREATE JSON RELATIONAL DUALITY VIEW driver_dv AS
SELECT JSON {'_id' : d.driver_id,
'name' : d.name,
'points' : d.points,
UNNEST
(SELECT JSON {'teamId' : t.team_id,
'team' : t.name WITH NOCHECK}
FROM team t WITH NOINSERT NOUPDATE NODELETE
WHERE t.team_id = d.team_id),
'race' :
[ SELECT JSON {'driverRaceMapId' : drm.driver_race_map_id,
UNNEST
(SELECT JSON {'raceId' : r.race_id,
'name' : r.name}
FROM race r WITH NOINSERT NOUPDATE NODELETE
WHERE r.race_id = drm.race_id),
'finalPosition' : drm.position}
FROM driver_race_map drm WITH INSERT UPDATE NODELETE
WHERE drm.driver_id = d.driver_id ]}
FROM driver d WITH INSERT UPDATE DELETE;
なんらかの理由でルート表driver
の(主キー以外の)フィールドをネストされたオブジェクトに配置する場合は、そのようにできます。たとえば、driverInfo
オブジェクトにフィールドname
およびpoints
をネストするとします。オプションで、フィールドdriverInfo
の前にキーワードNEST
を使用すると、ネストのデフォルト動作をより明示的に指定できます。
CREATE JSON RELATIONAL DUALITY VIEW driver_dv AS
SELECT JSON {'_id' : d.driver_id,
'driverInfo' : {'name' : d.name,
'points' : d.points},
UNNEST (SELECT JSON {...}),
'race' : ...}
FROM driver d;
ルート表の主キー・フィールドはネストできません。この場合、これはフィールド_id
を意味します。
例2-8 SQLを使用した、ネストされたドライバ情報での二面性ビューRACE_DVの作成
この例では、二面性ビューを作成し、ここでは配列result
の要素であるオブジェクトが次のようになります。これには、値がフィールドdriverId
およびname
を持つネストされたオブジェクトであるフィールドdriverInfo
が含まれています。
{"driverRaceMapId" : 3,
"position" : 1,
"driverInfo" : {"driverId" : 103, "name" : "Charles Leclerc"}}
CREATE JSON RELATIONAL DUALITY VIEW race_dv AS
SELECT JSON {'_id' : r.race_id,
'name' : r.name,
'laps' : r.laps WITH NOUPDATE,
'date' : r.race_date,
'podium' : r.podium WITH NOCHECK,
'result' :
[ SELECT JSON {'driverRaceMapId' : drm.driver_race_map_id,
'position' : drm.position,
'driverInfo' :
(SELECT JSON {'driverId' : d.driver_id,
'name' : d.name}
FROM driver d WITH NOINSERT UPDATE NODELETE
WHERE d.driver_id = drm.driver_id)}
FROM driver_race_map drm WITH INSERT UPDATE DELETE
WHERE drm.race_id = r.race_id ]}
FROM race r WITH INSERT UPDATE DELETE;
例2-9 SQLを使用した、ネストされていないドライバ情報での二面性ビューRACE_DVの作成
この例では、二面性ビューを作成し、ここでは配列result
の要素であるオブジェクトが次のようになります。これには、値がフィールドdriverId
およびname
を持つネストされたオブジェクトであるフィールドdriverInfo
が含まれていません。
{"driverId" : 103, "name" : "Charles Leclerc", "position" : 1}
'driverInfo' :
を使用して、表driver
の副問合せから生成されるオブジェクト値で上位レベルのフィールドdriverInfo
を定義するかわりに、ビュー定義はその副問合せの前にキーワードUNNEST
を付けます。その他の点では、このビュー定義は例2-8と同じです。
(作成されたビューは、例2-12のGraphQLを使用して作成されたビューと同じです。)
CREATE JSON RELATIONAL DUALITY VIEW race_dv AS
SELECT JSON {'_id' : r.race_id,
'name' : r.name,
'laps' : r.laps WITH NOUPDATE,
'date' : r.race_date,
'podium' : r.podium WITH NOCHECK,
'result' :
[ SELECT JSON {'driverRaceMapId' : drm.driver_race_map_id,
'position' : drm.position,
UNNEST
(SELECT JSON {'driverId' : d.driver_id,
'name' : d.name}
FROM driver d WITH NOINSERT UPDATE NODELETE
WHERE d.driver_id = drm.driver_id)}
FROM driver_race_map drm WITH INSERT UPDATE DELETE
WHERE drm.race_id = r.race_id ]}
FROM race r WITH INSERT UPDATE DELETE;
関連項目:
『Oracle Database SQL言語リファレンス』のCREATE JSON RELATIONAL DUALITY VIEWに関する項
親トピック: カーレースの例、二面性ビュー
2.4.2 GraphQLを使用したカーレース二面性ビューの作成
カーレース・アプリケーション用のチーム、ドライバおよびレースの二面性ビューを、GraphQLを使用して作成します。
GraphQLは、様々なデータベースで使用できるオープンソースの汎用問合せ言語かつデータ操作言語です。JSONリレーショナル二面性ビューを作成するために、Oracle Databaseでは、GraphQLの構文および操作のサブセットがサポートされています。「JSONリレーショナル二面性ビューに使用されるGraphQLの言語」では、サポートされているGraphQLのサブセットについて説明します。ここで説明していない構文と機能を紹介します。
GraphQL問合せおよび型定義は、GraphQLドキュメントとして表されます。ここで示すGraphQLの例は、カーレース二面性ビューを作成する場合、SQLの例に似ています。最もわかりやすい違いは構文です。
より重要な違いは、二面性ビューのGraphQL定義では、次のものを明示的に指定する必要がないということです:
-
ネストされたスカラー副問合せ。
-
子表に親表への外部キーが1つしかない場合、外部キー列と主キー(または一意キー)列の間の表リンク。脚注3
-
SQL/JSON生成ファンクション(またはそれと同等の構文短縮)の使用。
この情報は、かわりに、全体的な二面性ビュー定義に固有のグラフ/依存性の関係からすべて推測されます。二面性ビューの基礎となる表は、主キー(または一意キー)と外部キー間の関係によって、有向の依存関係グラフを形成します。ある表T-childから別の表T-parentへの外部キーは、ノードT-childからノードT-parentに向かうグラフ・エッジ(矢印)になります。
表のセットによって決定される依存関係グラフを作成する必要はありません。これは、二面性ビューを定義すると自動的に(暗黙的に)行われます。ただし、視覚化に役立つことがあります。
グラフのエッジ(矢印)は、外部キーを含む表を、主キーがその外部キーのターゲットである表にリンクします。たとえば、ノード(表) driver
からノード(表) team
への矢印は、表driver
の外部キーが表team
の主キーにリンクされていることを示します。図2-3では、矢印に外部キーおよび主キーのラベルが付いています。
JSONリレーショナル二面性ビューを定義するGraphQLコードは、GraphQL queryの形式(囲んでいるquery {
… }
コードを含まない)を取り、ビューで使用される依存関係グラフに基づいてグラフ構造を指定します。GraphQL二面性ビュー定義は、基礎となる表ごとに、サポートされているJSONドキュメントでJSONフィールドを生成するために使用される列を指定します。
GraphQLでは、ビュー定義問合せはGraphQLオブジェクト・スキーマで表されます。このスキーマは、基となる依存関係グラフと同様に、自動的に(暗黙的に)作成されます。二面性ビューの作成に使用される依存関係グラフまたはGraphQLオブジェクト・スキーマを作成または確認する必要はありませんが、それぞれについてある程度知っていると役立ちます。
GraphQLオブジェクト・スキーマは、GraphQLオブジェクト・タイプのセットで、二面性ビュー定義の場合、ビューの基礎となる表に基づいています。
二面性ビューを作成するためのGraphQL問合せ構文は、表依存関係グラフの構造を反映しており、オブジェクト・スキーマ構文に厳密に基づいています。(違いの1つは、使用される名前がSQLと互換性があることです。)
オブジェクト・スキーマでは、つまり問合せ構文では、各GraphQLオブジェクト・タイプ(表からマップされる)は、GraphQLフィールドによって名前が付けられます(JSONオブジェクトのフィールドと混同しないでください)。また、各GraphQLフィールドにはオプションで別名を指定できます。
GraphQL問合せはグラフを記述し、各ノードはタイプを指定します。グラフ内のノードの構文は、(GraphQL)フィールド名の後にそのオブジェクト・タイプが続きます。フィールドに別名がある場合は、その後にコロン(:
)を指定して、フィールド名の前に付けます。オブジェクト・タイプは、サブグラフを囲む中カッコ({
... }
)で表されます。フィールドの後にオブジェクト・タイプを指定する必要はなく、その場合はスカラーです。
GraphQLの構文は、SQLの構文とは異なります。特に、名前(識別子)の構文は異なります。GraphQL二面性ビュー定義では、GraphQL名として直接許可されていない表名および列名は、許可されている名前にマップされます。ただし、カーレースの例のようなすべてASCII英数字の単純な表名および列名は、二面性ビューのGraphQL定義で直接使用できます。
次に例を示します。
-
driverId : driver_id
別名
driverId
が前に付いたフィールドdriver_id
。 -
driver : driver {driverId : driver_id, name : name, points : points}
別名
driver
が前に付き、別名driverId
を持つフィールドdriver_id
と、それぞれフィールドと同じ名前の別名を持つフィールドname
およびpoints
が含まれるオブジェクト・タイプが後に続くフィールドdriver
。 -
driver {driverId : driver_id, name, points}
前述の例と同等です。対応するフィールド名と同じ別名は省略できます。
表に対応するオブジェクト・タイプでは、表の各列は列と同じ名前のスカラーGraphQLフィールドにマップされます。
ノート:
これらの各例では、別名driverId
が別名_id
に置き換えられます(ドキュメント識別子フィールドとして使用する場合、つまり、driver
がルート表、driver_id
が主キー列の場合)。
ノート:
GraphQLでは、カンマ(,
)は構文的にも意味的にも重要ではありません。これらはオプションであり、無視されます。読みやすくするために、このドキュメントでは、GraphQL {
…}
内のカンマを使用して、サポートされているドキュメント内の対応するJSONオブジェクトをより適切に提示します。
二面性ビューのGraphQL定義では、生成されたJSONドキュメントに単一オブジェクトを提供するノードと、そのようなオブジェクトの配列を提供するノードとの間に実際の違いはありません。{
… }
のみを使用して、ノードがGraphQLオブジェクト・タイプであることを指定できますが、これは、サポートされているJSONドキュメントでそのノードから生成されるJSONオブジェクトが1つのみであることを意味しません。
ただし、ビューがサポートするように設計されているJSONドキュメントをより厳密に反映するGraphQL二面性ビュー定義を保持するには、必要に応じて、オブジェクトの配列を提供するノードを大カッコ([
, ]
)で囲むことができます。
たとえば、{…},…
のみではなく[{…},…]
と記述すると、定義のこの部分によってドライバ・オブジェクトの配列が生成されることを示すことができます。このマニュアルでは、この規則に従っています。
これは人間がコードを読むためだけのものであることに注意してください。意味を成すところでは、大カッコはオプションです。ただし、意味を成さないところで使用すると、誤りを確認できるように構文エラーが発生します。
二面性ビューのルート表は、ビュー定義のGraphQLルート・フィールドとして使用します。たとえば、チーム・ドキュメントを定義する二面性ビューの場合は、ルートとして表team
から始めます(team {…}
と記述します)。
二面性ビュー定義の場合は表名である、タイプ名(team
など)に続く{
… }
内には、生成されるJSONフィールドの作成に使用するその表の列を指定します。
したがって、列名はGraphQLフィールド名として使用します。デフォルトでは、これらは、生成するJSONフィールドの名前にもなります。
必要なJSONフィールドの名前がその値を提供する列(GraphQLフィールド)の名前と同じでない場合は、列名の前に必要なJSONフィールドの名前を付け、2つの名前をコロン(:
)で区切ります。つまり、GraphQL別名を使用して、目的のJSONフィールド名を指定します。
たとえば、driverId : driver_id
は、列driver_id
のデータからJSONフィールドdriverId
を生成することを意味します。GraphQL用語では、driverId
は、(GraphQL)フィールドdriver_id
の別名です。
-
driver_id
のみを使用すると、その名前の列からJSONフィールドdriver_id
を生成することを意味します。 -
driverId : driver_id
を使用すると、列driver_id
のデータからJSONフィールドdriverId
を生成することを意味します。GraphQL用語では、driverId
は、GraphQLフィールドdriver_id
の別名です。
GraphQL問合せを作成して二面性ビューを作成する場合は、JSONフィールドをサポートする表依存関係グラフの列ごとにGraphQLフィールドを追加します。
さらに、二面性ビュー定義で使用される各表Tについて:
-
Tから親表T-parentへの外部キー・リンクごとに、T-parentという名前のフィールドを問合せに追加して、TからT-parentへのナビゲーションを許可します。このリンクは、1対1関係を実装します。単一の親T-parentが存在します。
-
表T-childからTへの外部キー・リンクごとに、T-childという名前のフィールドを問合せに追加して、TからT-childへのナビゲーションを許可します。このリンクは、1対多関係を実装します。タイプT-childの子が複数存在する場合があります。
中間オブジェクトのネスト解除(フラット化)は、二面性ビューのSQL定義の場合と同じですが、SQLキーワードUNNEST
のかわりに、GraphQLディレクティブ@unnest
を使用します。(ここで示すすべてのGraphQL二面性ビュー定義では、@unnest
を使用します。)
GraphQLでは、ハッシュ/番号記号文字#
が付いた行末コメントを挿入できます。この文字と、同じ行でこれに続く文字はコメントアウトされます。
例2-10 GraphQLを使用した二面性ビューTEAM_DVの作成
この例では、JSONドキュメントをサポートする二面性ビューを作成します。ここでは、チーム・オブジェクトには、値がチームのドライバを指定するネストされたオブジェクトの配列であるフィールドdriver
が含まれています。
{"_id" : 301, "name" : "Red Bull", "points" : 0, "driver" : [...]}
(作成されたビューは、例2-5のSQLを使用して作成されたビューと同じです。)
CREATE JSON RELATIONAL DUALITY VIEW team_dv AS
team @insert @update @delete
{_id : team_id,
name : name,
points : points,
driver : driver @insert @update
[ {driverId : driver_id,
name : name,
points : points @nocheck} ]};
例2-11 GraphQLを使用した二面性ビューDRIVER_DVの作成
この例では、JSONドキュメントをサポートする二面性ビューを作成します。ここでは、ドライバ・オブジェクトには、値がフィールドteamId
およびname
を持つネストされたオブジェクトであるフィールドteamInfo
が含まれていません。かわりに、表teamのデータが上位レベルで取り込まれ、チーム名がフィールドteam
となります。
{"_id" : 101,
"name" : "Max Verstappen",
"points" : 0,
"teamId" : 103,
"team" : "Red Bull",
"race" : [...]}
ここでは、2つのバージョンのビュー作成を示します。わかりやすくするために、1つ目のバージョンには更新可能性またはETAG計算の除外を宣言する注釈がありません。
CREATE JSON RELATIONAL DUALITY VIEW driver_dv AS
driver
{_id : driver_id,
name : name,
points : points,
team @unnest
{teamId : team_id,
name : name},
race : driver_race_map
[ {driverRaceMapId : driver_race_map_id,
race @unnest
{raceId : race_id,
name : name},
finalPosition : position} ]};
2つ目のバージョンのビュー作成には、更新可能性およびETAG @nocheck
の注釈があります。(例2-7のSQLを使用して作成されたビューと同じビューが作成されます。)
CREATE JSON RELATIONAL DUALITY VIEW driver_dv AS
driver @insert @update @delete
{_id : driver_id,
name : name,
points : points,
team @noinsert @noupdate @nodelete
@unnest
{teamId : team_id,
name : name @nocheck},
race : driver_race_map @insert @update @nodelete
[ {driverRaceMapId : driver_race_map_id,
race @noinsert @noupdate @nodelete
@unnest
{raceId : race_id,
name : name},
finalPosition : position} ]};
例2-12 GraphQLを使用した二面性ビューRACE_DVの作成
この例では、JSONドキュメントをサポートする二面性ビューを作成します。ここでは、配列result
の要素であるオブジェクトには、値がフィールドdriverId
およびname
を持つネストされたオブジェクトであるフィールドdriverInfo
が含まれていません:
{"driverId" : 103, "name" : "Charles Leclerc", "position" : 1}
ここでは、2つのバージョンのビュー作成を示します。わかりやすくするために、1つ目のバージョンには更新可能性またはETAG計算の除外を宣言する注釈がありません。
CREATE JSON RELATIONAL DUALITY VIEW race_dv AS
race
{_id : race_id,
name : name,
laps : laps,
date : race_date,
podium : podium,
result : driver_race_map
[ {driverRaceMapId : driver_race_map_id,
position : position,
driver
@unnest
{driverId : driver_id,
name : name}} ]};
2つ目のバージョンのビュー作成には、更新可能性およびETAG @nocheck
の注釈があります。(例2-9のSQLを使用して作成されたビューと同じビューが作成されます。)
CREATE JSON RELATIONAL DUALITY VIEW race_dv AS
race @insert @update @delete
{_id : race_id,
name : name,
laps : laps @noupdate,
date : race_date,
podium : podium @nocheck,
result : driver_race_map @insert @update @delete
[ {driverRaceMapId : driver_race_map_id,
position : position,
driver @noinsert @update @nodelete
@unnest
{driverId : driver_id,
name : name}} ]};
関連項目:
-
『Oracle Database SQL言語リファレンス』のCREATE JSON RELATIONAL DUALITY VIEWに関する項
親トピック: カーレースの例、二面性ビュー
脚注一覧
脚注1: ここで使用される表記では、Nは数値を表していません。単に"多数"、より正確には"1つ以上"の省略形です。脚注2: ここで使用される表記では、Nは数値を表していません。単に"多数"、より正確には"1つ以上"の省略形です。
脚注3: GraphQLで外部キー・リンクを明示的に使用する必要があるのは、2つの表の間に複数の外部キー関係がある場合、または表に同じ表を参照する外部キーがある場合のみです。このような場合は、
@link
ディレクティブを使用してリンクを指定します。「JSONリレーショナル二面性ビュー用のOracle GraphQLディレクティブ」を参照してください。