2 カーレース二面性ビューの例の概要

F1カーレースのデータは、JSONリレーショナル二面性ビューの機能を示すためにこのドキュメントで使用されます。

3種類のJSONドキュメント(ドライバ、レース、チーム)を使用するドキュメント中心のアプリケーションを考えます。これらの種類のドキュメントのそれぞれは、データを別の種類と共有しています。次に例を示します。

  • ドライバ・ドキュメントには、ドライバに関する情報、ドライバのチームの識別情報およびドライバが参加したレースに関する情報が含まれています。

  • レース・ドキュメントには、特定のレースに関する情報に、表彰者(1位、2位、3位の勝者)に関する情報および各ドライバのレースでの結果が含まれています。これらのいずれにも、ドライバ名とチーム名が含まれています。レーシング・データは1シーズンのレース用です。

  • チーム・ドキュメントには、チームに関する情報に、チームのドライバに関する情報が含まれています。

このデータに対してアプリケーションが実行する操作には、次のものがあります。

  • データベースに対するドライバ、レースまたはチームの追加または削除

  • ドライバ、レースまたはチームの情報の更新

  • チームへのドライバの追加、チームからのドライバの削除、またはチーム間でのドライバの移動

  • ドライバおよびレース情報へのレース結果の追加

この例の目的は、すべての共通情報を共有することです。つまり、ドライバ二面性ビューのID番号302のドライバは、チーム・ビューのドライバ番号302と同じです。

2つの二面性ビュー間で共通のデータの共有を指定するには、それらの間の関係を定義します。これは、二面性ビューの基礎となる表の主キーと外部キーの指定によって実行します。

特定の二面性ビューを定義すると、ビューでサポートされるドキュメントへの挿入、削除または更新が可能かどうか、それらの制約のオーバーライド、サポートされているドキュメントでの特定のフィールドの挿入、削除または更新が可能かどうかを制御できます。デフォルトでは、二面性ビューは読取り専用です。ドキュメントの挿入、削除または更新は実行できません。

関連項目:

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にあります。

  • ドライバ・ドキュメントと共有されるチーム情報は、フィールドdriverdriverIdnameおよび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はこのフィールドに対応しており、表の主キーです。

  • レースまたはチーム・ドキュメントと共有されないドライバ情報は、フィールド_idnameおよび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はこのフィールドに対応しており、表の主キーです。

  • ドライバまたはチーム・ドキュメントと共有されないレース情報は、フィールド_idname (上位レベル)、lapsdatetimeおよびpositionにあります。

  • ドライバ・ドキュメントと共有されるレース情報は、driverIdなどのフィールドにあり、その値はドライバ・ドキュメントのドキュメント識別子フィールド(_id)の値です。

  • チーム・ドキュメントと共有されるレース情報は、フィールドteam (podiumの下にあるwinnerfirstRunnerUpおよび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に対応するドライバの名前およびポイントのみが含まれています。

  • レース・エンティティは、ドライバ・ドキュメントまたはチーム・ドキュメントにないレース・ドキュメントのコンテンツのみを表します。これには、ドキュメント・フィールドnamelapsdateおよびpodiumに対応するレースの名前、ラップ数、日付および表彰者情報のみが含まれています。

  • チーム・エンティティは、ドキュメントまたはレース・ドキュメントにないチーム・ドキュメントのコンテンツのみを表します。これには、ドキュメント・フィールドnameおよびpointsに対応するチームの名前およびポイントのみが含まれています。

2つのエンティティは、カーディナリティに従って関連しています。このような関係には次の3つのタイプがあります: 脚注1

1対1 (1: 1)
エンティティAのインスタンスは、エンティティB1つのインスタンスにのみ関連付けることができます。たとえば、1人のドライバは1つのチームにのみ存在できます。
1対多(1: N)
エンティティAのインスタンスは、エンティティB1つ以上のインスタンスに関連付けることができます。たとえば、チームには多数のドライバを含めることができます。
多対多(N:N)
エンティティAのインスタンスは、エンティティB1つ以上のインスタンスに関連付けることができ、その逆も可能です。たとえば、レースには多くのドライバがあり、ドライバは多くのレースに参加できます。

多対1 (N:1)の関係は、反対の視点から見ると、1対多の関係にすぎません。1対多のみを使用します。

図2-1を参照してください。矢印は関係の方向を示し、矢印は2番目のカーディナリティを示します。たとえば、エンティティteamからエンティティdriverへの1:Nの矢印はdriverの方向を指し、1つのチームが多くのドライバに関連していることを示します。

図2-1 カーレースの例、方向を示したエンティティ関係図(1)

図2-1の説明が続きます
「図2-1 カーレースの例、方向を示したエンティティ関係図(1)」の説明

ドライバは、1つのチームにのみ関連付けることができます(1:1)。チームは、複数のドライバに関連付けることができます(1:N)。ドライバは、複数のレースに関連付けることができます(N:N)。レースは、複数のドライバに関連付けることができます(N:N)。

関連項目:

Database normalization (Wikipedia)

2.3 カーレースの例、表

正規化されたエンティティは、データベース表としてモデル化されます。エンティティ関係は、主キー列と外部キー列間のリンク(制約)としてモデル化されます。表teamdriverおよびraceは、カーレース・アプリケーションで使用されるチーム、ドライバおよびレースJSONドキュメントを提供およびサポートする二面性ビューを実装するために使用されます。

正規化されたエンティティでは、コンテンツは重複していません。ただし、別の表に格納されているコンテンツを参照する表として、論理的に重複させるためにエンティティを実装するデータベースが必要です。これを実現するには、外部キー制約を使用して、他の表にリンクされている列を追加します。これは、共通のコンテンツの共有を実装する表間の外部キー関係です。

二面性ビューの定義に使用する表は、次の要件を満たす必要があります(それ以外の場合、ビューを作成しようとするとエラーが発生します)。

  • ビューの上位レベル(ルート)表には、表の行を一意に識別する1つ以上の列で構成される主キーが必要です。これにより、NULL値が可能な一意キーまたはNULL列を持つ一意キーを使用するために起こる曖昧さが回避されます。

    主キー列の値は、サポートするように表が設計されているJSONドキュメントのドキュメント識別子フィールド(_id)の値に対応します(「二面性ビューのドキュメント識別子フィールド」を参照)。(カーレースの例で使用される各表の主キー列は、1つのみです。)

  • 二面性ビューの定義に使用される他の各表には、主キーまたは一意キーも必要です。一意キーは、表内の行を一意に識別する1つ以上の列のセットです。主キーがない場合は、一意キーの少なくとも1つの列をNULLにしないでください。

  • 各主キーと各一意キーには、一意の索引が定義されている必要があります。各外部キー列にも索引を定義することをお薦めします。主キーと外部キー間の参照(リンク)を定義する必要がありますが、適用する必要はありません。

    ノート:

    1次索引および一意索引は通常、主キーおよび一意キー整合性制約を定義するときに暗黙的に作成されます。ただし、これは保証されておらず、索引の作成後に削除できます。必要な索引が存在することを確認する必要があります。『Oracle Database管理者ガイド』索引の作成に関する項を参照してください。

一意キーと同様に、主キーおよび外部キーは、複数の列で構成されるコンポジットにできます。このドキュメントでは通常、これらは単一列のキーと呼びますが、キーが言及されるたびにこの可能性を念頭に置いてください。

一般に、外部キー列の値はNULLでもかまいません。前述の要件以外に、外部キー列をNULL値可能にしない場合は、表定義でNOT NULLとしてマークします。

カーレースの例では、チーム、ドライバおよびレースのエンティティは、表teamdriverおよび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関係を直接実装しません。かわりに、マッピング表(または関連表)と呼ばれる別の表を追加して、表driverrace間の関係の橋渡しをする必要があります。マッピング表には、外部キーとして、関連付けられている2つの表の主キー列が含まれています。

N:Nのエンティティ関係は、1:Nの関係と同等で、その後に1:1の関係が続きます。この等価性により、表driverraceの間にマッピング表driver_race_mapを追加して、データベース表を使用したN:Nのエンティティ関係が実装されます。

図2-2は、図2-1と同等です。中間エンティティd-r-mapが追加され、各N:Nの関係が1:Nの関係に拡張され、その後に1:1の関係が続きます。 脚注2

図2-2 カーレースの例、方向を示したエンティティ関係図(2)

図2-2の説明が続きます
「図2-2 カーレースの例、方向を示したエンティティ関係図(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データ型は、次のとおりです: JSONBLOBCLOBNCLOBVARCHAR2NVARCHAR2CHARNCHARRAWBOOLEANDATETIMESTAMPTIMESTAMP WITH TIME ZONEINTERVAL YEAR TO MONTHINTERVAL DAY TO SECONDNUMBERBINARY_DOUBLEおよびBINARY_FLOAT。他の列データ型を指定すると、エラーが発生します。

関連項目:

2.4 カーレースの例、二面性ビュー

チーム、ドライバおよびレースの二面性ビューでは、カーレース・アプリケーションで使用されるチーム、ドライバおよびレースのJSONドキュメントが提供およびサポートされています。

ビューは、関連表driverraceおよびteamのデータの他、マッピング表driver_race_mapに基づいています。関連表はそれぞれビューdriver_dvrace_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文字列("")が生成されます。ただし、データ型VARCHAR2NVARCHAR2および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言語のサブセットを使用して、二面性ビューを作成できます。

関連項目:

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では、矢印に外部キーおよび主キーのラベルが付いています。

図2-3 カーレースの例、表依存関係グラフ

図2-3の説明が続きます
「図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}} ]};

関連項目:



脚注一覧

脚注1: ここで使用される表記では、Nは数値を表していません。単に"多数"、より正確には"1つ以上"の省略形です。
脚注2: ここで使用される表記では、Nは数値を表していません。単に"多数"、より正確には"1つ以上"の省略形です。
脚注3: GraphQLで外部キー・リンクを明示的に使用する必要があるのは、2つの表の間に複数の外部キー関係がある場合、または表に同じ表を参照する外部キーがある場合のみです。このような場合は、@linkディレクティブを使用してリンクを指定します。「JSONリレーショナル二面性ビュー用のOracle GraphQLディレクティブ」を参照してください。