7 JSONリレーショナル二面性ビューに使用されるGraphQLの言語
GraphQLは、様々なデータベースで使用できるオープンソースの汎用問合せ言語かつデータ操作言語です。JSONリレーショナル二面性ビューを作成するために、Oracle Databaseでは、GraphQLの構文および操作のサブセットがサポートされています。
この章では、GraphQLのサポートされるサブセットについて説明します。「GraphQLを使用したカーレース二面性ビューの作成」で説明されていない構文および機能について紹介します。ここでは、GraphQLを使用した二面性ビューの作成の簡単な例をいくつか示します。
GraphQLを使用した二面重ビューの作成でサポートされているOracle構文は、GraphQL仕様(2021年10月)のセクションB.1、B.2およびB.3で指定されているGraphQLの適切なサブセットです。ただし、ユーザーが指定した名前は、ここで指定するOracle固有のルールを満たす必要があります。
Oracle GraphQL構文には、JSONリレーショナル二面性ビューでの使用を容易にするための追加のオプション機能もあります。GraphQLをプログラムで使用する必要があり、標準のGraphQL構文の使用を続ける場合、これを実行できます。その必要がない場合は、オプションの構文機能が便利なことがあります。
GraphQLをよく理解している読者の場合、サポートされている言語のサブセットには、次の標準のGraphQL構文は含まれていません:
-
ミューテーションとサブスクリプション。サポートされる操作は問合せのみです。
-
インライン・フラグメント。事前定義済のFragmentSpread構文のみがサポートされています。
-
型定義(型インタフェース、共用体、列挙型、入力オブジェクト、および型拡張)。GraphQLオブジェクトおよびスカラーの型定義のみがサポートされています。
-
変数定義。
GraphQLを使用して二面性ビューを定義すると、SQLを使用して定義するよりも利点があります。これについては、「GraphQLを使用したカーレース二面性ビューの作成」で説明します。要約すると、GraphQL構文はより単純で冗長性が低くなります。JSON生成副問合せの結果間の明示的な結合を使用して、サポートされているドキュメントとその部分の形式を記述する必要があると、煩雑でエラーが発生しやすくなります。
Oracle GraphQLの二面性ビューのサポートには、次の構文拡張および簡略化が含まれています:
-
スカラー型
Oracle Databaseでは、Oracle JSON言語のスカラー型およびSQLのスカラー型に対応する追加のGraphQLスカラー型がサポートされています。「Oracle GraphQLスカラー型」を参照してください。
-
暗黙的なGraphQLフィールド別名
二面性ビュー定義で使用される別名未指定のGraphQLフィールド名は、実際のGraphQLフィールド名の別名として自動的に取得されます。実際に、これは、二面性ビューでサポートされるドキュメントのフィールド名に対応する、大文字と小文字を区別する照合を行うための簡潔な方法です。「暗黙的なGraphQLフィールド別名」を参照してください。
-
すべてのスカラー・フィールドのワイルドカード(
*
)二面性ビュー定義では、特定のGraphQL型の各スカラー・フィールドを明示的にリストするかわりに、アスタリスクのワイルドカード
*
を使用できます。*
をディレクティブ@upper
とともに使用すると、フィールド名が引用符で囲まれていない場合、大文字の別名で暗黙的に指定されます。*
をディレクティブ@exclude
とともに使用すると、引数fields
で指定されたフィールド以外のすべてのフィールドを含めることができます。「スカラーGraphQLフィールドのワイルドカード(*)」を参照してください。
-
二面性ビュー用GraphQLディレクティブ
@upper
および@exclude
(スカラーGraphQLフィールドのワイルドカード(*)を参照)に加えて、Oracle GraphQLには、二面性ビューの定義時に特定の処理を指定する他のディレクティブ(@link
、@
[un
]nest
および@flex
)が用意されています。「JSONリレーショナル二面性ビュー用のOracle GraphQLディレクティブ」を参照してください。 -
二面性ビュー定義のGraphQL名
二面性ビュー定義で使用する表および列の名前が標準のGraphQLフィールド名として直接使用できる場合は、そのまま使用されます。たとえば、カーレースの二面性ビューの場合です。
一般的に、二面性ビュー定義では、(1) JSONフィールド名、(2) GraphQL型とフィールド名、(3) SQL表と列名の間のマッピングを指定します。最初の2つは大/小文字が区別されますが、引用符なしのSQL名は大/小文字が区別されません。また、名前で許可される文字は、GraphQLとSQLで異なります。
このような理由から、Oracleは、二面性ビュー定義で許可される引用符なしのGraphQL名を緩和および拡張します。
「GraphQL二面性ビュー定義で使用される名前」を参照してください。
Oracle GraphQLスカラー型
表7-1に、Oracle JSONスカラー型およびOracle SQLスカラー型に対応する、OracleでサポートされているGraphQLスカラー型を示します。標準のGraphQL型とカスタムのOracle固有のGraphQL型の両方がリストされます。
表7-1 スカラー型: Oracle JSON、GraphQLおよびSQL
Oracle JSON言語スカラー型 | GraphQLスカラー型 | SQLスカラー型 |
---|---|---|
binary |
Binary (Oracle固有) |
RAW またはBINARY |
date |
Date (Oracle固有) |
|
timestamp |
Timestamp (Oracle固有) |
|
timestamp with time zone |
TimestampWithTimezone (Oracle固有) |
|
year-month interval |
YearmonthInterval (Oracle固有) |
|
day-second interval |
DaysecondInterval (Oracle固有) |
|
double |
Float (標準GraphQL) |
|
float |
Float (標準GraphQL) |
|
暗黙的なGraphQLフィールド別名
二面性ビュー定義の本体は、GraphQL問合せです。フィールド名が別名なしでその問合せで使用されている場合、対応するGraphQLフィールド名を選択するために、大/小文字を区別しないで照合されます。標準のGraphQL問合せでは、このような照合で大/小文字が区別されます。
この便利な機能によって、基本的に、別名のないフィールドには、ビュー定義で使用されている大/小文字で別名が付けられます。別名は、サポートされているドキュメントで使用されるJSONフィールド名に直接対応します。実際のGraphQLフィールド名は、SQL表または列名から導出されます:
たとえば、GraphQLフィールド名がmyfield
(小文字)として定義され、二面性ビューの作成問合せでmyField
を使用する場合、問合せ対象フィールドはmyField : myfield
と記述されているように暗黙的に処理され、ビューでサポートされているJSONドキュメントにはmyField
というJSONフィールドが含まれています。
スカラーGraphQLフィールドのワイルドカード(*
)
アスタリスクのワイルドカード*
を使用することは、特定のGraphQL型の各スカラー・フィールドを明示的にリストするのではない、代替の簡単な方法です。ディレクティブ@upper
とともに使用すると、引用符なしのフィールド名は大文字の別名で暗黙的に指定されます。
*
を使用する場合、対象となるスカラー・フィールドには別名を指定できません。
例2-10では、table
チームのすべての列が、二面性ビューteam_dv
の作成に使用されます:
CREATE JSON RELATIONAL DUALITY VIEW team_dv AS
team
{teamId : team_id,
name : name,
points : points,
driver : ...}
これらのスカラー・フィールド(列)、team_id
、name
およびpoints
に別名が使用されていない場合は、個別にリストするかわりに、ワイルドカード*
を使用できます。
次の定義はすべて同等です。(3番目の例では、別名は冗長で、GraphQL型名と同じであり、表team
の列名と同じです。)
CREATE JSON RELATIONAL DUALITY VIEW team_dv AS
team
{*,
driver : ...}
CREATE JSON RELATIONAL DUALITY VIEW team_dv AS
team
{team_id,
name,
points,
driver : ...}
CREATE JSON RELATIONAL DUALITY VIEW team_dv AS
team
{team_id : team_id,
name : name,
points : points,
driver : ...}
ディレクティブ@upper
をワイルドカード*
とともに使用すると、すべての大文字のフィールド名のセットを表すことができます。次の定義は同等です:
CREATE JSON RELATIONAL DUALITY VIEW team_dv AS
team
{* @upper,
driver : ...}
CREATE JSON RELATIONAL DUALITY VIEW team_dv AS
team
{TEAM_ID : team_id,
NAME : name,
POINTS : points,
driver : ...}
また、ディレクティブ@exclude
をワイルドカード*
とともに使用すると、引数fields
で指定されたフィールド以外のすべてのフィールドを取得できます。(除外するフィールドのリストに主キー・フィールドを含めることはできません。除外するとエラーが発生します。)
たとえば、次は同等です(例2-12の定義とは異なり、フィールド名として、raceId
ではなくrace_id
を使用し、フィールドdate
およびpodium
を排除します):
CREATE JSON RELATIONAL DUALITY VIEW race_dv AS
race
{raceId : race_id,
name : name,
laps : laps,
date : race_date,
podium : podium,
result : ...}
CREATE JSON RELATIONAL DUALITY VIEW race_dv AS
race
{raceId : race_id,
date : race_date,
* @exclude (fields : ["laps" "podium"],
result : ...}
GraphQL二面性ビュー定義で使用される名前
Oracleは、二面性ビュー定義で許可される引用符なしのGraphQL名を緩和および拡張します。これは、(1)二面性ビューでサポートされるJSONドキュメントのフィールド名の指定、(2) GraphQL名でのSQL識別子構文(表および列に使用)の使用を容易にするために行われます。
GraphQL二面性ビュー定義で使用する名前のnoneにピリオド(ドット)文字(.
)が含まれているか、引用符で囲む必要がある場合、対応するGraphQLスキーマはGraphQL標準に完全に準拠しています。この場合、既存のすべてのGraphQLツールと連携する必要があります。
それ以外の場合(より一般的な場合)、完全準拠ではありません。JSONリレーショナル二面性ビューの作成に使用できますが、一部のGraphQLツールでは正しく動作しない可能性があります。
標準GraphQL名は、次の方法で制限されます:
-
英数字のASCII文字とアンダースコア(
_
)文字のみを含めることができます。 -
2つのアンダースコア文字(
__
)で始めることはできません。
SQL名に引用符を付けると、二重引用符("
) (引用符、コード・ポイント34とも呼ばれる)とnull (コード・ポイント0)を除く任意の文字を含めることができます。引用符なしのSQL名には、英数字(ASCIIまたはこれ以外)、アンダースコア(_
)、番号記号(#
)、ドル記号($
)を使用できます。完全修飾の表名にはピリオド(ドット)文字(.
)が含まれ、データベース・スキーマ(ユーザー)名と表名を区切ります。
二面性ビュー定義で許可されるGraphQL名には、次のルールが適用されます。これらのルールの末尾は、完全修飾SQL表名、つまり、データベース・スキーマ(ユーザー)名、ピリオド(ドット)文字(.
)およびデータベース表名の3つの部分で構成される<schema name>
.
<table name>
という形式の名前に適用されます。その他のルールは、ドットを含まないSQL名に適用されます。
-
引用符で囲まれたSQL名(識別子)に対応するGraphQL名は、同じ引用符で囲まれた名前です。
たとえば、
"this name"
はSQLとGraphQLで同じです。 -
ASCII英数字またはアンダースコア(
_
)文字のみで構成される引用符なしのSQL名に対応するGraphQL名は、次の点を除いてSQL名と同じです:-
GraphQL フィールド名は小文字です。
たとえば、GraphQLフィールド名
MY_NAME
は、SQL名my_name
に対応します。 -
GraphQL型名の最初の文字は大文字です。
たとえば、GraphQL型名
My_name
は、SQL名MY_NAME
に対応します。
-
-
非ASCII英数字、番号記号(
#
)、またはドル記号($
)文字を1つ以上含む引用符なしのSQL名に対応するGraphQL名は同じ名前ですが、大文字で引用符付きです。(Oracle SQLでは、このような名前は引用符で囲まれているかどうかに関係なく、大/小文字が区別されません。)たとえば、GraphQL名
"MY#NAME$4"
は、SQL名my#name$4
に対応します -
完全修飾SQL表名に対応するGraphQL名は、形式が
<schema name>
.
<table name>
で、(1)<schema name>
に対応するGraphQL名と、(2)ピリオド(ドット)文字(.
)と、(3)<table name>
に対応するGraphQL名を連結したものです。GraphQL名では、ドットが引用符で囲まれていないことに注意してください。完全修飾SQL名の例:
-
GraphQL名
My_schema.Mytable
は、SQL名MY_SCHEMA.MYTABLE
に対応します。 -
GraphQL名
"mySchema".Mytable
は、SQL名"mySchema".mytable
に対応します。 -
GraphQL名
"mySchema".
は、SQL名"my table"
"mySchema"."my table"
に対応します。 -
GraphQL名
"Schema#3.Table$4"
は、SQL名SCHEMA#3.TABLE$4
に対応します。
-
関連項目:
- JSONリレーショナル二面性ビュー用のOracle GraphQLディレクティブ
GraphQLディレクティブは、GraphQLスキーマの追加情報または特定の動作を指定する注釈です。二面性ビューを定義するためのすべてのOracle GraphQLディレクティブは、GraphQLフィールドに適用されます。
関連トピック
7.1 JSONリレーショナル二面性ビュー用のOracle GraphQLディレクティブ
GraphQLディレクティブは、GraphQLスキーマの追加情報または特定の動作を指定する注釈です。二面性ビューを定義するためのすべてのOracle GraphQLディレクティブは、GraphQLフィールドに適用されます。
ディレクティブは、接頭辞@
が付いた名前で、場合によっては引数が続きます。
二面性ビューを定義するためのOracle GraphQLには、次のディレクティブがあります:
-
ディレクティブ
@flex
は、JSON
型の列を二面性ビュー用のフレックス列として指定します。このディレクティブの使用については、「フレックス列: 二面性ビューのスキーマの柔軟性と展開」を参照してください。 -
ディレクティブ
@nest
および@unnest
は、二面性ビュー定義の中間オブジェクトのネストおよびネスト解除(フラット化)を指定します。これらは、それぞれSQLキーワードNEST
およびUNNEST
に対応します。デフォルトでは、ルート表列に対応するフィールドはネストされず、ルート以外の表の列に対応するフィールドはネストされます。ルート表の主キー列に対応するフィールドはネストできません。ネストしようとするとエラーが発生します。
例7-1に、
@nest
の使用例を示します。@unnest
を使用する例については、「GraphQLを使用したカーレース二面性ビューの作成」を参照してください。 -
@upper
および@exclude
ディレクティブは、GraphQL型のスカラー・フィールドを指定する場合のアスタリスク(*
)ワイルドカードの動作を修飾します。これらは、「スカラーGraphQLフィールドのワイルドカード(*)」で説明されています。 -
ディレクティブ
@link
は、列間の複数の外部キー・リンクを区別します。「Oracle GraphQLディレクティブ@link」を参照してください。 -
ディレクティブ
@
[no
]update
、@
[no
]insert
および@
[no
]delete
は、注釈を更新する二面性ビューとして機能します。これらは、SQL注釈キーワード[NO
]UPDATE
、[NO
]INSERT
および[NO
]DELETE
に対応しており、「注釈(NO)UPDATE、(NO)INSERT、(NO)DELETEによる更新操作の許可/禁止」で説明されています。 -
ディレクティブ
@
[no
]check
は、オプティミスティックな同時実行性制御に対応する二面性ビューの部分を決定します。これらは、SQL注釈キーワード[NO
]CHECK
に対応しています。詳細は、「GraphQLを使用したカーレース二面性ビューの作成」を参照してください。
例7-1 ネストされたドライバ情報を使用した二面性ビューDRIVER_DV1の作成
この例では、二面性ビューdriver_dv1
を作成しています。これは、例2-11でGraphQLを使用して定義され、例2-7でSQLを使用して定義されたビューdriver_dv
と同じです。ただし、表driver
の列のフィールドname
およびpoints
は、フィールドdriverInfo
の値であるサブオブジェクトでネストされます。脚注1フィールドdriverInfo
の指定は、ビューdriver_dv1
の定義と元のビューdriver_dv
の定義の違いのみです。
driver_dv1
の対応するGraphQL定義およびSQL定義を示します。
CREATE JSON RELATIONAL DUALITY VIEW driver_dv1 AS
driver
{_id : driver_id,
driverInfo : driver @nest {name : name,
points : points},
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} ]};
次に対応するSQL定義を示します:
CREATE JSON RELATIONAL DUALITY VIEW driver_dv1 AS
SELECT JSON {'_id' : d.driver_id,
'driverInfo' : {'name' : d.name,
'points' : d.points},
UNNEST
(SELECT JSON {'teamId' : t.team_id,
'team' : t.name}
FROM team t
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
WHERE r.race_id = drm.race_id),
'finalPosition' : drm.position}
FROM driver_race_map drm
WHERE drm.driver_id = d.driver_id ]}
FROM driver d;
表driver
はビューのルート表であるため、デフォルトでフィールドはすべてビューにネストされず、GraphQLで@nest
を使用してネストする必要があります。
(ルート以外の表のフィールドはデフォルトでネストされており、ネストを解除するには@unnest
(SQLではキーワードUNNEST
)を明示的に使用する必要があります。これは、チーム・フィールドteamId
とname
、およびレース・フィールドraceId
とname
の場合です。)
- Oracle GraphQLディレクティブ@link
GraphQLディレクティブ@link
は、列間の複数の外部キー・リンクを区別します。
7.1.1 Oracle GraphQLディレクティブ@link
GraphQLディレクティブ@link
は、列間の複数の外部キー・リンクを区別します。
ディレクティブ@link
は、外部キー列と主キー列または一意キー列の間のリンクを、二面性ビューの基礎となる表で指定します。通常、列は別の表のためのものですが、同じ表の列もリンクできます。この場合、外部キーは自己参照と呼ばれます。
一般に、外部キー・リンクを明示的に指定する必要がないという点は、二面性ビュー定義に対してGraphQLが示す、SQLより優れている利点です。このようなリンクは通常、基礎となる表依存関係グラフによって推測されるため、冗長性が低くなります。
GraphQLで外部キー・リンクを明示的に使用する必要があるのは、2つの表の間に複数の外部キー関係がある場合、または表に同じ表を参照する外部キーがある場合のみです。このような場合は、@link
ディレクティブを使用して、特定のリンク(外部キーと方向)を指定します。
例7-2のteam_w_lead
表定義には、列lead_driver
からdriver
表の列driver_id
への外部キー・リンクがあります。また、driver
表には、列team_id
からteam_w_lead
表の主キー列team_id
への外部キー・リンクがあります。
図7-1の表依存関係グラフは、これら2つの依存関係を示しています。これは図2-3のグラフと同じですが、表team_w_lead
の外部キー列lead_driver
から表driver
の主キー列driver_id
への追加リンクが含まれている点が異なります。
対応するチームの二面性ビューの定義は、例7-3および例7-4にあります。
@link
ディレクティブには、to
またはfrom
という名前の単一の引数が必要です。この引数では、値がネストされたオブジェクトである二面性ビュー・フィールドに対して、(1)ネストされたオブジェクトのフィールドを定義する列を持つ表の外部キー(to
方向)を使用するか、(2)列がオブジェクトのフィールドのネスト/囲みを使用するかを定義する列を持つ表の外部キーを使用するか(from
方向)を指定します。
to
またはfrom
引数の値は文字列のGraphQLリストで、各文字列は単一の外部キー列(たとえば、to : ["fkcol"]
)を指定します。複数の文字列のGraphQLリストは、複合外部キー(to : ["fkcol1", "fkcol2"]
など)を表します。(GraphQLリストは、JSON配列に対応しています。カンマは、GraphQLではオプションです。)
例7-2 LEAD_DRIVER列を使用した表TEAM_W_LEADの作成
この例では、表team_w_lead
を作成します。これは、例2-4の表team
と同じです。ただし、表driver
の列driver_id
への外部キーである追加の列lead_driver
がある点が異なっています。
CREATE TABLE team_w_lead
(team_id INTEGER GENERATED BY DEFAULT ON NULL AS IDENTITY,
name VARCHAR2(255) NOT NULL UNIQUE,
lead_driver INTEGER,
points INTEGER NOT NULL,
CONSTRAINT team_pk PRIMARY KEY(team_id)
CONSTRAINT lead_fk FOREIGN KEY lead_driver REFERENCES driver(driver_id));
また、表driver
には、表team_w_lead
の列team_id
を参照する外部キー列team_id
があります。表team_w_lead
とdriver
の間に2つの外部キー・リンクがあるため、これらの表を使用するチームおよびドライバの二面性ビューでは、例7-3および例7-4に示すように、ディレクティブ@link
を使用する必要があります。
例7-3 GraphQLディレクティブ@linkを示す、LEAD_DRIVERを使用した二面性ビューTEAM_DV2の作成
この例は例2-10と似ていますが、例7-2で定義されている表team_w_lead
を使用しており、これには外部キー列lead_driver
があります。表team_w_lead
とdriver
の間に2つの外部キー関係があるため、ディレクティブ@link
を使用して、使用する外部キーとその場所を指定する必要があります。
最上位レベルのJSONフィールドleadDriver
の値は、表team_w_lead
の外部キー列lead_driver
によって提供されるドライバ・オブジェクトです。最上位フィールドdriver
の値は、表driver
の外部キー列team_id
によって提供されるドライバ・オブジェクトのJSON配列です。
フィールドleadDriver
の@link
引数は、from
を使用します。その値lead_driver
が、外部にある/ネストするオブジェクトの基礎となる表team_w_lead
の外部キー列であるためです。
フィールドdriver
の@link
引数はto
を使用します。その値team_id
が、内部にある/ネストされるオブジェクトの基礎となる表driver
の外部キー列であるためです。
CREATE JSON RELATIONAL DUALITY VIEW team_dv2 AS
team_w_lead
{_id : team_id,
name : name,
points : points,
leadDriver : driver @link (from : ["lead_driver"])
{driverId : driver_id,
name : name,
points : points},
driver : driver @link (to : ["team_id"])
[ {driverId : driver_id,
name : name,
points : points} ]};
例7-4 GraphQLディレクティブ@linkを示す、二面性ビューDRIVER_DV2の作成
この例は例2-11と似ていますが、例7-2で定義されている表team_w_lead
を使用しており、これには外部キー列lead_driver
があります。表team_w_lead
とdriver
の間に2つの外部キー関係があるため、ディレクティブ@link
を使用して、使用する外部キーとその場所を指定する必要があります。
フィールドteam
の@link
引数はfrom
を使用します。その値team_id
が、外部にある/ネストするオブジェクトの基礎となる表driver
の外部キー列であるためです。
CREATE JSON RELATIONAL DUALITY VIEW driver_dv2 AS
driver
{_id : driver_id
name : name
points : points
team : team_w_lead
@link (from: ["team_id"])
@unnest
{teamId : team_id,
name : name}
race : driver_race_map
[ {driverRaceMapId : driver_race_map_id,
race @unnest
{raceId : race_id,
name : name}
finalPosition : position} ]};
脚注一覧
脚注1: 注釈の更新およびETAGチェックはここには表示されません。