標準 SQL のスクリプト

BigQuery スクリプト

BigQuery スクリプトを使用すると、1 回のリクエストで複数のステートメントを BigQuery に送信して、変数を使用したり、IFWHILE などの制御フロー ステートメントを使用できます。たとえば、変数を宣言し、値を代入し、第 3 の場所にあるステートメントからその変数を参照できます。

BigQuery のスクリプトは、順番に実行される SQL ステートメントのリストです。SQL ステートメント リストは、セミコロンで区切られた有効な BigQuery ステートメントのリストです。

例:

-- Declare a variable to hold names as an array.
DECLARE top_names ARRAY<STRING>;
-- Build an array of the top 100 names from the year 2017.
SET top_names = (
  SELECT ARRAY_AGG(name ORDER BY number DESC LIMIT 100)
  FROM `bigquery-public-data`.usa_names.usa_1910_current
  WHERE year = 2017
);
-- Which names appear as words in Shakespeare's plays?
SELECT
  name AS shakespeare_name
FROM UNNEST(top_names) AS name
WHERE name IN (
  SELECT word
  FROM `bigquery-public-data`.samples.shakespeare
);

スクリプトは他のクエリと同様に、jobs.insert を使用して BigQuery で実行され、クエリテキストとして複数ステートメント スクリプトが指定されます。スクリプトが実行されると、子ジョブと呼ばれる追加のジョブがスクリプト内の各ステートメントに作成されます。jobs.list を呼び出し、parentJobId パラメータとしてスクリプトのジョブ ID を渡すことで、スクリプトの子ジョブを列挙できます。

jobs.getQueryResults がスクリプトで呼び出されると、スクリプトで実行する最後の SELECT、DML、または DDL ステートメントのクエリ結果が返されます。上記のステートメントが実行されていない場合、クエリ結果は返されません。スクリプト内のすべてのステートメントの結果を取得するには、子ジョブを列挙し、それぞれに対して jobs.getQueryResults を呼び出します。

BigQuery では、CREATE TEMP FUNCTION ステートメントが含まれていない場合、複数のステートメントを含むリクエストは、最後にクエリ ステートメントを含むスクリプトとして解釈されます。たとえば、以下はスクリプトと見なされません。

CREATE TEMP FUNCTION Add(x INT64, y INT64) AS (x + y);

SELECT Add(3, 4);

DECLARE

DECLARE variable_name[, ...] [variable_type] [DEFAULT expression];

variable_name は、有効な識別子である必要があります。また、variable_type は BigQuery の任意のタイプです。

説明

指定された型の変数を宣言します。たとえば DEFAULT 句が指定された場合、変数は式の値で初期化されます。DEFAULT 句が指定されない場合、変数は値 NULL で初期化されます。

[variable_type] を省略する場合、DEFAULT 句を指定する必要があります。変数の型は、DEFAULT 句の式の型によって推定されます。

変数の宣言は、スクリプトの先頭、他のステートメントの前、または BEGIN が宣言されたブロックの先頭に置きます。変数名は大文字と小文字を区別しません。

複数の変数名を 1 つの DECLARE ステートメント内に記述できます。ただし、variable_typeexpression は 1 つだけです。

現在のブロックまたは格納中のブロックですでに宣言されている変数と同じ名前の変数を宣言するとエラーになります。

たとえば DEFAULT 句が存在する場合、式の値は指定された型に強制型変換できる必要があります。同じブロックまたは格納中のブロック内ですでに宣言されているその他の変数を参照できます。

変数の最大サイズは 1 MB で、スクリプトで使用されるすべての変数の最大サイズは 10 MB です。

次の例では、変数 x を INT64 として値 NULL で初期化しています。

DECLARE x INT64;

次の例では、変数 d を DATE として現在の日付の値で初期化しています。

DECLARE d DATE DEFAULT CURRENT_DATE();

次の例では、xyzINT64 として値 0 で初期化しています。

DECLARE x, y, z INT64 DEFAULT 0;

次の例では、dataset1.products テーブルの任意の項目に対応する item という名前の変数を宣言しています。item の型はテーブル スキーマから推測されます。

DECLARE item DEFAULT (SELECT item FROM dataset1.products LIMIT 1);

SET

構文

SET name = expression;
SET (variable_name_1, variable_name_2, …, variable_name_n) =
  (expression_1, expression_2, …, expression_n);

説明

変数が指定された式の値を持つように設定するか、または複数の式の結果に基づいて複数の変数を同時に設定します。

SET スクリプト本文内のどこにでも記述できます。

次の例では、変数 x の値を 5 に設定しています。

SET x = 5;

次の例では、a の値を 4、b の値を 'foo'、c の値を false にそれぞれ設定しています。

SET (a, b, c) = (1 + 3, 'foo', false);

次の例では、クエリの結果を複数の変数に代入しています。まず、2 つの変数 target_wordcorpus_count を宣言します。次に、SELECT AS STRUCT クエリの結果を 2 つの変数に割り当てます。クエリの結果は、2 つのフィールドを持つ STRUCT を含む 1 つの行です。最初の要素は最初の変数に割り当てられ、2 番目の要素は 2 番目の変数に割り当てられます。

DECLARE target_word STRING DEFAULT 'methinks';
DECLARE corpus_count, word_count INT64;

SET (corpus_count, word_count) = (
  SELECT AS STRUCT COUNT(DISTINCT corpus), SUM(word_count)
  FROM `bigquery-public-data`.samples.shakespeare
  WHERE LOWER(word) = target_word
);

SELECT
  FORMAT('Found %d occurrences of "%s" across %d Shakespeare works',
         word_count, target_word, corpus_count) AS result;

このステートメント リストは、次の文字列を出力します。

Found 151 occurrences of "methinks" across 38 Shakespeare works

EXECUTE IMMEDIATE

構文

EXECUTE IMMEDIATE sql_expression [ INTO variable[, ...] ] [ USING identifier[, ...] ];

sql_expression:
  { "query_statement" | expression("query_statement") }

identifier:
  { variable | value } [ AS alias ]

説明

動的 SQL ステートメントをすぐに実行します。

  • sql_expression: クエリ ステートメント、クエリ ステートメントで使用できる式、単一の DDL ステートメント、または単一の DML ステートメントを表します。
  • expression: 関数条件式式サブクエリのいずれかです。
  • query_statement: 実行する有効なスタンドアロン SQL ステートメントを表します。値を返す場合、INTO 句には同じ型の値を含める必要があります。USING 句にあるシステム変数と値の両方にアクセスできます。他のすべてのローカル変数とクエリ パラメータは、クエリ ステートメントに公開されません。
  • INTO 句: SQL 式の実行後、INTO 句を使用して結果を 1 つ以上の変数に格納できます。
  • USING 句: SQL 式の実行前、USING 句から 1 つ以上の識別子を SQL 式に渡すことができます。これらの識別子はクエリ パラメータと同様に機能し、クエリ ステートメントに値を公開します。識別子は変数または値です。

USING 句で参照される識別子の query_statement には、次のプレースホルダを含めることができます。

  • ?: このプレースホルダの値は、インデックスで USING 句の識別子にバインドされます。

    -- y = 1 * (3 + 2) = 5
    EXECUTE IMMEDIATE "SELECT ? * (? + 2)" INTO y USING 1, 3;
    
  • @identifier: このプレースホルダの値は、名前で USING 句の識別子にバインドされます。この構文はクエリ パラメータの構文と同じです。

    -- y = 1 * (3 + 2) = 5
    EXECUTE IMMEDIATE "SELECT @a * (@b + 2)" INTO y USING 1 as a, 3 as b;
    

EXECUTE IMMEDIATE ステートメントの動作に関するその他の注意事項は次のとおりです。

  • EXECUTE IMMEDIATE は、ネストされた要素として動的に実行されません。
  • EXECUTE IMMEDIATE ステートメントが結果を返す場合、それらの結果はステートメント全体の結果になり、適切なシステム変数が更新されます。
  • 同じ変数を INTO 句と USING 句の両方に使用できます。
  • query_statement には、他のステートメント(BEGIN...END など)を含む単一の解析済みステートメントを含めることができます。
  • ゼロ行の値テーブルからも含めて、query_statement からゼロ行が返される場合、INTO 句のすべての変数は NULL に設定されます。
  • ゼロ行の値のテーブルからも含めて、1 つの行が query_statement から返される場合、値は変数名ではなく位置で割り当てられます。
  • INTO 句が存在する場合、query_statement から複数の行を返そうとするとエラーがスローされます。

この例では、書籍の表を作成してその表にデータを入力します。変数の参照、変数への値の保存、式の使用にはさまざまな方法があります。

-- create some variables
DECLARE book_name STRING DEFAULT 'Ulysses';
DECLARE book_year INT64 DEFAULT 1922;
DECLARE first_date INT64;

-- Create a temporary table called Books.
EXECUTE IMMEDIATE
  "CREATE TEMP TABLE Books (title STRING, publish_date INT64)";

-- Add a row for Hamlet (less secure)
EXECUTE IMMEDIATE
  "INSERT INTO Books (title, publish_date) VALUES('Hamlet', 1599)";

-- add a row for Ulysses, using the variables declared at the top of this
-- script and the ? placeholder
EXECUTE IMMEDIATE
  "INSERT INTO Books (title, publish_date) VALUES(?, ?)"
  USING book_name, book_year;

-- add a row for Emma, using the identifier placeholder
EXECUTE IMMEDIATE
  "INSERT INTO Books (title, publish_date) VALUES(@name, @year)"
  USING 1815 as year, "Emma" as name;

-- add a row for Middlemarch, using an expression
EXECUTE IMMEDIATE
  CONCAT("INSERT INTO Books (title, publish_date)", "VALUES('Middlemarch', 1871)");

-- save the publish date of the first book, Hamlet, to a variable called first_date
EXECUTE IMMEDIATE "SELECT publish_date FROM Books LIMIT 1" INTO first_date;

+------------------+------------------+
| title            | publish_date     |
+------------------+------------------+
| Hamlet           | 1599             |
| Ulysses          | 1922             |
| Emma             | 1815             |
| Middlemarch      | 1871             |
+------------------+------------------+

BEGIN

構文

BEGIN
  sql_statement_list
END;

説明

BEGIN は、宣言された変数が対応する END まで存在するステートメントのブロックを開始します。sql_statement_list は、それぞれがセミコロンで終わるゼロ個以上の SQL ステートメントのリストです。

変数宣言は、ブロックの先頭で、その他のタイプのステートメントよりも前に配置する必要があります。ブロック内で宣言された変数は、そのブロック内とネストされたブロック内でのみ参照できます。同じブロックまたは外側のブロックで宣言されている変数と同じ名前の変数を宣言するとエラーになります。

ブロックや条件文(BEGIN / ENDIF / ELSE / END IFWHILE / END WHILE など)の最大のネストレベルは 50 です。

BEGIN / END は、ネストされた要素として動的に実行されません。

次の例では、変数 x のデフォルト値が 10 と宣言されています。そしてブロックが開始され、変数 y の値が x(つまり 10)に割り当てられています。この値が戻り値になります。次に、END ステートメントがブロックの最後となり、変数 y のスコープもここで終了となります。最後に、x の値が返されます。

DECLARE x INT64 DEFAULT 10;
BEGIN
  DECLARE y INT64;
  SET y = x;
  SELECT y;
END;
SELECT x;

BEGIN...EXCEPTION

構文

BEGIN
  sql_statement_list
EXCEPTION WHEN ERROR THEN
  sql_statement_list
END;

説明

BEGIN...EXCEPTION はステートメントのブロックを実行します。ステートメントのいずれかにエラーが発生した場合、スクリプトは残りのブロックをスキップし、EXCEPTION 句のステートメントを実行します。

EXCEPTION 句内では、次の EXCEPTION システム変数を使用することでエラーの詳細にアクセスできます。

名前 説明
@@error.formatted_stack_trace STRING @@error.stack_trace のコンテンツは人が読める文字列として表現されます。この値は表示を目的に使用され、予告なく変更されることがあります。プログラムによるエラーのスタック トレースへのアクセスには、代わりに @@error.stack_trace を使用してください。
@@error.message STRING 人が読めるエラー メッセージを指定します。
@@error.stack_trace 1 をご覧ください。 配列の各要素は、エラーの時点で実行しているステートメントまたはプロシージャ コールに対応し、現在実行中のスタック フレームが先頭に表示されます。各フィールドの意味の定義は、次のとおりです。
  • 行 / 列: スタック フレームの行番号と列番号を 1 から開始して指定します。フレームがプロシージャの本文内で発生した場合、line 1 column 1 はプロシージャの先頭にある BEGIN キーワードに対応します。
  • ロケーション: フレームがプロシージャ本文内にある場合、[project_name].[dataset_name].[procedure_name] 形式でプロシージャのフルネームを指定します。フレームがトップレベル スクリプト内の場所を参照している場合、このフィールドは NULL になります。
  • ファイル名: 将来の使用のために予約されています。常に NULL です。
@@error.statement_text STRING エラーの原因となったステートメントのテキストを指定します。

1: @@error.stack_trace の型は ARRAY<STRUCT<line INT64, column INT64, filename STRING, location STRING>> です。

BigQuery はエラー メッセージをいつでも修正できるため、@@error.message の使用にあたっては、エラー メッセージが常に同じである、または一定のパターンであることを想定しないでください。エラー メッセージからテキストを抽出してエラーの場所情報を取得せず、代わりに @@error.stack_trace@@error.statement_text を使用してください。

例外ハンドラによってスローされる(そして、処理されない)例外を処理するには、個別の例外ハンドラを使用して外側のブロック内にあるブロックをラップする必要があります。

外側のブロックに別の例外ハンドラを使用する方法は次のとおりです。

BEGIN
  BEGIN
    ...
  EXCEPTION WHEN ERROR THEN
    SELECT 1/0;
  END;
EXCEPTION WHEN ERROR THEN
  -- The exception thrown from the inner exception handler lands here.
END;

BEGIN...EXCEPTION ブロックは、他の BEGIN ブロック同様に DECLARE ステートメントもサポートします。BEGIN ブロックで宣言されている変数は、BEGIN セクションでのみ有効で、ブロックの例外ハンドラでは使用できません。

CREATE OR REPLACE PROCEDURE dataset1.proc1() BEGIN
  SELECT 1/0;
END;

CREATE OR REPLACE PROCEDURE dataset1.proc2() BEGIN
  CALL dataset1.proc1();
END;

BEGIN
  CALL dataset1.proc2();
EXCEPTION WHEN ERROR THEN
  SELECT
    @@error.message,
    @@error.stack_trace,
    @@error.statement_text,
    @@error.formatted_stack_trace;
END;

この例では、ゼロ除算のエラーが発生した場合、スクリプト全体が終了するのではなく、BigQuery が dataset1.proc1()dataset1.proc2() を終了し、例外ハンドラで SELECT ステートメントを実行します。例外ハンドラが実行されると、変数の値は次のようになります。

変数
@@error.message "Query error: division by zero: 1 / 0 at <project>.dataset1.proc1:2:3]"
@@error.stack_trace [
STRUCT(2 AS line, 3 AS column, NULL AS filename, "<project>.dataset1.proc1:2:3" AS location),
STRUCT(2 AS line, 3 AS column, NULL AS filename, "<project>.dataset1.proc2:2:3" AS location),
STRUCT(10 AS line, 3 AS column, NULL AS filename, NULL AS location),
]
@@error.statement_text "SELECT 1/0"
@@error.formatted_stack_trace "At <project>.dataset1.proc1[2:3]\nAt <project>.dataset1.proc2[2:3]\nAt [10:3]"

END

BEGIN で開始されたブロックを終了します。BEGIN / END は、ネストされた要素として動的に実行されません。

IF

構文

IF condition THEN [sql_statement_list]
[ELSEIF condition THEN sql_statement_list]
[ELSEIF condition THEN sql_statement_list]...
[ELSE  sql_statement_list]
END IF;

説明

条件が true の場合は最初の sql_statement_list を、条件が一致しない場合はオプションの ELSE sql_statement_list を実行します。

ブロックや条件文(BEGIN / ENDIF / ELSE / END IFWHILE / END WHILE など)の最大のネストレベルは 50 です。

IF は、ネストされた要素として動的に実行されません。

次の例では、INT64 変数 target_product_id のデフォルト値が 103 と宣言されています。この宣言によりテーブル dataset.productsproduct_id 列を持つ行を含み target_product_id の値と一致するかどうかがチェックされます。一致する場合は、プロダクトが見つかったという文字列と default_product_id の値が出力されます。一致しない場合は、プロダクトが見つからなかったという文字列と default_product_id の値が出力されます。

DECLARE target_product_id INT64 DEFAULT 103;
IF EXISTS (SELECT 1 FROM dataset.products
           WHERE product_id = target_product_id) THEN
  SELECT CONCAT('found product ', CAST(target_product_id AS STRING));
  ELSEIF EXISTS (SELECT 1 FROM dataset.more_products
           WHERE product_id = target_product_id) THEN
  SELECT CONCAT('found product from more_products table',
  CAST(target_product_id AS STRING));
ELSE
  SELECT CONCAT('did not find product ', CAST(target_product_id AS STRING));
END IF;

ループ

LOOP

構文

LOOP
  sql_statement_list
END LOOP;

説明

BREAK または LEAVE ステートメントでループが終了するまで、sql_statement_list が実行されます。sql_statement_list は、それぞれがセミコロンで終わるゼロ個以上の SQL ステートメントのリストです。LOOP は、ネストされた要素として動的に実行されません。

次の例では、変数 x のデフォルト値が 0 と宣言されています。次に、LOOP ステートメントを使用してループを作成しています。ループは、x が 10 以上になるまで実行されます。ループが終了すると、x の値が出力されます。

DECLARE x INT64 DEFAULT 0;
LOOP
  SET x = x + 1;
  IF x >= 10 THEN
    LEAVE;
  END IF;
END LOOP;
SELECT x;

この例では、次を出力します。

+----+
| x  |
+----+
| 10 |
+----+

WHILE

構文

WHILE boolean_expression DO
  sql_statement_list
END WHILE;

ブロックや条件文(BEGIN / ENDIF / ELSE / END IFWHILE / END WHILE など)の最大のネストレベルは 50 です。

説明

boolean_expression が true の場合は、sql_statement_list が実行されます。boolean_expression は、ループのイテレーションごとに評価されます。WHILE は、ネストされた要素として動的に実行されません。

BREAK

説明

現在のループを終了します。

BREAK をループの外側で使用するとエラーが発生します。

次の例では、変数 headsheads_count が宣言されています。次に、ループを開始します。ループ内では、ランダムなブール値が heads に割り当てられています。次に、heads が true の場合に「Heads!」(コインの表)と出力され、heads_count が増分されます。true でない場合は「Tails!」(コインの裏)と出力され、ループが終了します。コインのフリップが表になった回数を表す文字列が出力されます。

DECLARE heads BOOL;
DECLARE heads_count INT64 DEFAULT 0;
LOOP
  SET heads = RAND() < 0.5;
  IF heads THEN
    SELECT 'Heads!';
    SET heads_count = heads_count + 1;
  ELSE
    SELECT 'Tails!';
    BREAK;
  END IF;
END LOOP;
SELECT CONCAT(CAST(heads_count AS STRING), ' heads in a row');
### LEAVE [`BREAK`](#break)と同義。 ### CONTINUE **説明** 現在のループ内の次のステートメントをスキップし、ループの先頭に戻ります。`CONTINUE` をループの外側で使用するとエラーが発生します。**例** 次の例では、「heads」と「heads_count」という 2 つの変数が宣言されています。次に、ランダムなブール値を「heads」に割り当てるループを開始し、「heads」が true かどうかを確認します。true の場合、「Heads!」(コインの表)を出力し、「heads_count」を増分し、ループを再開し、残りのステートメントをスキップします。false の場合、「Trails!」(コインの裏)を出力し、ループを終了します。最後に、コインのフリップが表になった回数を表す文字列が出力されます。
DECLARE heads BOOL;
DECLARE heads_count INT64 DEFAULT 0;
LOOP
  SET heads = RAND() < 0.5;
  IF heads THEN
    SELECT 'Heads!';
    SET heads_count = heads_count + 1;
    CONTINUE;
  END IF;
  SELECT 'Tails!';
  BREAK;
END LOOP;
SELECT CONCAT(CAST(heads_count AS STRING), ' heads in a row');

ITERATE

CONTINUE と同義。

RAISE

構文

RAISE [USING MESSAGE = message];

説明

USING MESSAGE = message が指定されると、必要に応じて特定のエラー メッセージを使用して、エラーを発生させます。

USING MESSAGE が指定されていない場合

RAISE ステートメントは EXCEPTION 句内でのみ使用する必要があります。RAISE ステートメントは検出された例外を再生成し、元のスタック トレースを保持します。

USING MESSAGE が指定されている場合

RAISE ステートメントが BEGIN...EXCEPTION ブロックの BEGIN セクションに含まれている場合、次のようになります。

  • ハンドラが呼び出されます。
  • @@error.message の値は、指定された message 文字列(messageNULL の場合は NULL になる可能性があります)と完全に一致します。

  • スタック トレースは、RAISE ステートメントに設定されます。

RAISE ステートメントが BEGIN...EXCEPTION ブロックの BEGIN セクションに含まれていない場合、RAISE ステートメントは指定したエラー メッセージを表示し、スクリプトの実行を終了します。

RETURN

BigQuery スクリプトでは、RETURN は現在のスクリプトの実行を終了します。

CALL

構文

CALL procedure_name (procedure_argument[, …])

説明

引数リストとともにプロシージャを呼び出します。procedure_argument は、変数または式とすることが可能です。OUT 引数または INOUT 引数は、引数として渡される変数ごとに適切な BigQuery のタイプが指定される必要があります。

同じ変数を、プロシージャの引数リストに OUT 引数または INOUT 引数として複数回指定することはできません。

プロシージャ呼び出しの最大深度は 50 フレームです。

CALL は、ネストされた要素として動的に実行されません。

次の例では、変数 retCode を宣言しています。次に、引数 'someAccountId'retCode を渡し、データセット myDataset 内でプロシージャ updateSomeTables を呼び出します。最後に、retCode の値を返します。

DECLARE retCode INT64;
-- Procedure signature: (IN account_id STRING, OUT retCode INT64)
CALL myDataset.UpdateSomeTables('someAccountId', retCode);
SELECT retCode;

システム変数

システム変数を使用して、スクリプトの実行中に情報を確認できます。

名前 説明
@@current_job_id STRING 現在実行中のジョブのジョブ ID。スクリプトのコンテキストでは、スクリプト全体ではなく、現在のステートメントを処理するジョブが返されます。
@@last_job_id STRING 現在のスクリプトで実行された最新のジョブのジョブ ID。現在のジョブは含まれません。スクリプトに CALL ステートメントが含まれている場合、このジョブは別のプロシージャで作成された可能性があります。
@@project_id STRING 現在のクエリを実行するために使用されるプロジェクトの ID。プロシージャのコンテキストでは、@@project_id はプロシージャを所有するプロジェクトではなく、スクリプトを実行しているプロジェクトを指します。
@@row_count INT64 スクリプトで使用され、前のスクリプト文が DML の場合、その DML ステートメントの結果として変更、挿入、または削除された行数を指定します。前のステートメントが MERGE ステートメントの場合、@@row_count は挿入、削除された合計行数を表します。スクリプト内にない場合、この値は NULL になります。
@@script.bytes_billed INT64 現在実行中のスクリプト ジョブでこれまでに請求された合計バイト数。スクリプト内にない場合、この値は NULL になります。
@@script.bytes_processed INT64 現在実行中のスクリプト ジョブでこれまでに処理された合計バイト数。スクリプト内にない場合、この値は NULL になります。
@@script.creation_time TIMESTAMP 現在実行中のスクリプト ジョブの作成時刻。スクリプト内にない場合、この値は NULL になります。
@@script.job_id STRING 現在実行中のスクリプト ジョブのジョブ ID。スクリプト内にない場合、この値は NULL になります。
@@script.num_child_jobs INT64 現在完了している子ジョブの数。スクリプト内にない場合、この値は NULL になります。
@@script.slot_ms INT64 スクリプトがそれまでに使用したスロットのミリ秒数。スクリプト内にない場合、この値は NULL になります。
@@time_zone STRING 明示的なタイムゾーンが引数として指定されていない場合に、タイムゾーンに依存する SQL 関数で使用するデフォルトのタイムゾーン。他のシステム変数とは異なり、@@time_zoneSET ステートメントを使用して任意の有効なタイムゾーン名に変更できます。各スクリプトの先頭で、@@time_zone は「UTC」で始まります。

上記のシステム変数に加えて、スクリプト実行中に EXCEPTION システム変数を使用できます。例外ハンドラで使用されない場合、EXCEPTION システム変数は NULL になります。以下は EXCEPTION システム変数です。

  • @@error.formatted_stack_trace
  • @@error.message
  • @@error.stack_trace
  • @@error.statement_text

EXCEPTION システム変数の詳細については、BEGIN...EXCEPTION をご覧ください。

権限

テーブル、モデル、その他のリソースへのアクセス権は、実行時にチェックされます。ステートメントが実行されない場合、または式が評価されない場合、BigQuery は、スクリプトを実行するユーザーが参照しているリソースにアクセスできるかどうかをチェックしません。

スクリプト内で、各式またはステートメントの権限は別々に検証されます。たとえば、次のスクリプトについて考えてみます。

SELECT * FROM dataset_with_access.table1;
SELECT * FROM dataset_without_access.table2;

スクリプトを実行するユーザーに table1 へのアクセス権があるが、table2 へのアクセス権がない場合、最初のクエリは成功し、2 番目のクエリは失敗します。スクリプト ジョブ自体も失敗します。

セキュリティの制約

動的 SQL は便利ですが、不正使用の可能性が高まります。たとえば、次のクエリを実行すると、テーブル パラメータが不適切にフィルタリングされ、意図しないテーブルにアクセスして実行される可能性があるため、セキュリティ上の脅威となりえます。

EXECUTE IMMEDIATE CONCAT(‘SELECT * FROM ’, @employee_table);

テーブル内の機密データの公開や漏洩しないために、あるいは DROP TABLE などのコマンドを実行してテーブル内のデータを削除しないようにするために、BigQuery の動的 SQL スクリプトは、SQL インジェクション攻撃への露出を減らすための複数のセキュリティ対策をサポートしています。

  • 動的 SQL に渡されたパラメータに埋め込まれた複数の SQL ステートメントを実行することはできません。
  • 次のコマンドは動的に実行されません。BEGIN / ENDCALLIFLOOPWHILEEXECUTE IMMEDIATE

構成フィールドの制限

次のクエリ構成フィールドはスクリプト用に設定できません:

  • clustering
  • create_disposition
  • destination_table
  • destination_encryption_configuration
  • range_partitioning
  • schema_update_options
  • time_partitioning
  • user_defined_function_resources
  • write_disposition