@LINKディレクティブ

@LINKディレクティブは、表間の複数の外部キー関係の曖昧さを排除したり、同じ表内の自己参照外部キーを指定します。

表関数と二面性ビューの両方で、表を結合またはリンクする際に使用する外部キーを明示的に定義します。通常、外部キー・リンクは自動的に推測されるため、常に@linkを指定する必要があるわけではありません。外部キー制約が定義されていない場合、同じ2つの表間に複数の外部キー関係がある場合、または表にその表自体に対する外部キー参照がある(自己参照)場合は、@linkディレクティブを使用する必要があります。

関連する表の間に外部キー制約が存在しない場合は、@linkディレクティブをfromtoの両方の引数とともに使用して、結合列を明示的に指定する必要があります。外部キー制約が存在し、可能な関係が1つのみの場合、@linkはオプションであり、Oracleによって自動的に結合する正しい列が推測されます。ただし、同じ表間に可能な外部キー関係が複数ある場合、または関係があいまいな場合は、@linkを使用して、使用する外部キーを指定します。

@linkは、from引数またはto引数、あるいはその両方を受け取ります。
  • from - リンク元のソース表またはオブジェクトの列を指定します。
  • to - リンクの接続先となるターゲット表またはオブジェクトの列を指定します。
使用する外部キーまたはその方向があいまいな場合は、関係を明確にするために、fromまたはtoのうち少なくとも1つを指定する必要があります。ただし、表の間に外部キー制約が定義されていない場合は、fromtoの両方を指定して、表の結合方法を明示的に指定する必要があります。
「カー・レース・データセットの設定」で、drivers表に、teams表のteam_id列を参照する外部キーteam_idがあったことを思い出してください。
CREATE TABLE driver
  (driver_id  INTEGER PRIMARY KEY,
   name       VARCHAR2(255) NOT NULL UNIQUE,
   points     INTEGER NOT NULL,
   team_id    INTEGER,
   CONSTRAINT driver_fk FOREIGN KEY(team_id) REFERENCES team(team_id));

次の例では、@linkディレクティブを使用して結合列を明示的に指定します:

例3-1 結合列を指定する@linkディレクティブ

SELECT JSON_SERIALIZE(data PRETTY) AS data FROM GRAPHQL('
    team {
        teamId: team_id
        teamName: name
        teamPoints: points
        drivers: driver @link(from: ["TEAM_ID"], to: ["TEAM_ID"]) {
            driverId: driver_id
            driverName: name
            driverPoints: points
        }
    }
');
複合結合列を指定する場合を除き、@linkの角括弧はオプションです。前述の例では、角括弧の有無にかかわらず、同じ出力が生成されます:
DATA                                                                           
--------------------------------------------------------------------------------
{                                                                              
  "teamId" : 301,                                                              
  "teamName" : "McLaren Mercedes",                                             
  "teamPoints" : 666,                                                          
  "drivers" :                                                                  
  [                                                                            
    {                                                                          
      "driverId" : 101,                                                        
      "driverName" : "Lando Norris",                                           
      "driverPoints" : 282                                                     
    },                                                                         
    {                                                                          
      "driverId" : 102,                                                        
      "driverName" : "Oscar Piastri",                                          
      "driverPoints" : 384                                                     
    }                                                                          
  ]                                                                            
}                                                                              
                                                                                 
{                                                                              
  "teamId" : 302,                                                              
  "teamName" : "Ferrari",                                                      
  "teamPoints" : 652,                                                          
  "drivers" :                                                                  
  [                                                                            
    {                                                                          
      "driverId" : 103,                                                        
      "driverName" : "Charles Leclerc",                                        
      "driverPoints" : 312                                                     
    },                                                                         
    {                                                                          
      "driverId" : 104,                                                        
      "driverName" : "Carlos Sainz Jr.",                                       
      "driverPoints" : 340                                                     
    }                                                                          
  ]                                                                            
}        
..............................
..............................
10 rows selected.

@linkディレクティブは、通常、GraphQLを使用したJSONリレーショナル二面性ビューの作成に使用されます。詳細な例については、この項を参照してください。

同じ表を参照する外部キー関係を識別するための@linkディレクティブ

このシナリオを理解するために、同じ表を参照する外部キーを持つ新しい表を作成してデータを挿入します。

例3-2 自己参照フィールドを持つ新しい表の作成およびデータの挿入

CREATE TABLE driver_w_lead 
  (driver_id  INTEGER PRIMARY KEY,
   name       VARCHAR2(255) NOT NULL UNIQUE,
   points     INTEGER NOT NULL,
   team_id    INTEGER,
   lead_driver_id INTEGER,
   CONSTRAINT driver_w_lead_team_fk FOREIGN KEY(team_id) REFERENCES team(team_id),
   CONSTRAINT driver_w_lead_fk FOREIGN KEY(lead_driver_id) REFERENCES driver_w_lead(driver_id));

INSERT INTO driver_w_lead (driver_id, name, points, team_id, lead_driver_id) VALUES
  (101, 'Lando Norris', 282, 301, NULL),
  (102, 'Oscar Piastri', 384, 301, 101),
  (103, 'Charles Leclerc', 312, 302, NULL),
  (104, 'Carlos Sainz Jr.', 340, 302, 103),
  (105, 'Max Verstappen', 456, 303, NULL),
  (106, 'Sergio Pérez', 133, 303, 105),
  (107, 'Lewis Hamilton', 240, 304, NULL),
  (108, 'George Russell', 228, 304, 107),
  (109, 'Fernando Alonso', 58, 305, NULL),
  (110, 'Lance Stroll', 36, 305, 109),
  (111, 'Esteban Ocon', 33, 306, NULL),
  (112, 'Pierre Gasly', 32, 306, 111),
  (113, 'Nico Hülkenberg', 30, 307, NULL),
  (114, 'Kevin Magnussen', 28, 307, 113),
  (115, 'Daniel Ricciardo', 24, 308, NULL),
  (116, 'Yuki Tsunoda', 22, 308, 115),
  (117, 'Alexander Albon', 12, 309, NULL),
  (118, 'Logan Sargeant', 5, 309, 117),
  (119, 'Valtteri Bottas', 3, 310, NULL),
  (120, 'Zhou Guanyu', 1, 310, 119);
SELECT JSON_SERIALIZE(data PRETTY) AS data FROM GRAPHQL('
    driver_w_lead {
        id: driver_id
        name
        points
        team @unnest {
            teamName: name
        }
        driver_w_lead @link(from: lead_driver_id) @unnest {
            leadDriver: name
        }
    }
');