EXECUTE IMMEDIATE FROM¶
EXECUTE IMMEDIATE FROM は、ステージ内のファイルで指定された SQL ステートメントを実行します。ファイルには SQL ステートメントまたは Snowflakeスクリプトブロック を含めることができます。ステートメントは構文的に正しい SQL ステートメントにする必要があります。
EXECUTE IMMEDIATE FROM コマンドを使用すると、どのSnowflakeセッションからでもファイル内のステートメントを実行できます。
この機能は、Snowflakeオブジェクトとコードの展開と管理を制御するメカニズムを提供します。たとえば、ストアドスクリプトを実行して、すべてのアカウントに標準のSnowflake環境を作成することができます。構成スクリプトには、新しいアカウントごとにユーザー、ロール、データベース、スキーマを作成するステートメントが含まれる場合があります。
Jinja2テンプレート化¶
EXECUTE IMMEDIATE FROM は、Jinja2テンプレート化言語を使ってテンプレートファイルを実行することもできます。テンプレートには変数や式を含めることができ、ループや条件分岐、変数の置換、マクロなどを使用することができます。テンプレートには、他のテンプレートを含めることもでき、ステージングされた他のファイルで定義されたマクロをインポートすることもできます。
テンプレート化言語の詳細については、 Jinja2ドキュメント をご参照ください。
実行するファイルは以下の条件を満たす必要があります。
構文的に有効なJinja2テンプレートであること。
ステージまたは Gitリポジトリのクローン にあります。
構文的に有効な SQL ステートメントをレンダリングできること。
テンプレート化によって、より柔軟な制御構造と、環境変数を使用したパラメーター化を実現できます。たとえば、テンプレートを使用して、スクリプトで定義したオブジェクトの展開ターゲットを動的に選択することができます。SQL スクリプトをレンダリングするためにテンプレートを使用するには、 テンプレートディレクティブ を使用するか、少なくとも1つのテンプレート変数を持つ USING 句 を追加します。
テンプレート化ディレクティブ¶
2つのテンプレートディレクティブのいずれかを使うことができます。
推奨ディレクティブは SQL の有効な構文を使います。
--!jinja
オプションで、代替ディレクティブを使うこともできます。
#!jinja
注釈
ディレクティブの前には、バイトオーダーマークと最大10文字までの空白文字(改行、タブ、スペース)のみを配置することができます。ディレクティブの後に続く文字は無視されます。
ステージングされたファイルのコンテンツをテンプレートで使用する方法¶
テンプレートは SnowflakeFile API から直接、またはJinja2の include、 import、および inheritance 機能を使って他のステージングされたファイルをロードできます。
ファイルは絶対パスで参照できます。
{% include "@my_stage/path/to/my_template" %}
{% import "@my_stage/path/to/my_template" as my_template %}
{% extends "@my_stage/path/to/my_template" %}
{{ SnowflakeFile.open("@my_stage/path/to/my_template", 'r', require_scoped_url = False).read() }}
インクルード、インポート、エクステンドは相対パスもサポートし、 SnowflakeFile API はスコープされたSnowflakeファイル URLs をサポートします。
{% include "my_template" %}
{% import "../my_template" as my_template %}
{% extends "/path/to/my_template" %}
- こちらもご参照ください。
構文¶
EXECUTE IMMEDIATE
FROM { absoluteFilePath | relativeFilePath }
[ USING ( <key> => <value> [ , <key> => <value> [ , ... ] ] ) ]
[ DRY_RUN = { TRUE | FALSE } ]
条件:
absoluteFilePath ::= @[ <namespace>. ]<stage_name>/<path>/<filename>relativeFilePath ::= '[ / | ./ | ../ ]<path>/<filename>'
必須パラメーター¶
絶対ファイルパス(absoluteFilePath)¶
namespace内部ステージまたは外部ステージが存在するデータベースまたはスキーマ、あるいはその両方で、
database_name.schema_nameまたはschema_nameの形式です。データベースとスキーマがユーザーセッション内で現在使用されている場合、名前空間は オプション です。それ以外の場合は必須です。stage_name内部または外部ステージの名前。
pathステージ内にある、大文字と小文字を区別したファイルへのパス。
filename実行するファイルの名前。構文的に正しく、有効な SQL ステートメントが含まれている必要があります。各ステートメントはコンマで区切る必要があります。
相対ファイルパス(relativeFilePath)¶
pathステージ内にある、大文字と小文字を区別したファイルへの相対パス。相対パスは、先頭の
/でステージのファイルシステムのルートを示し、./で現在のディレクトリ(親ファイルがあるディレクトリ)を参照し、../で親ディレクトリを参照するなど、確立された規則をサポートします。詳細については、 使用上の注意 をご参照ください。filename実行するファイルの名前。構文的に正しく、有効な SQL ステートメントが含まれている必要があります。各ステートメントはコンマで区切る必要があります。
オプションのパラメーター¶
USING ( <key> => <value> [ , <key> => <value> [ , ... ] ] )-
テンプレート展開のパラメーターとして使用できる、1つ以上のキーと値のペアを渡すことができます。キーと値のペアはコンマ区切りのリストを形成する必要があります。
USING 句がある場合、ファイルは SQL スクリプトとして実行される前に、まず Jinja2テンプレートとしてレンダリング されます。
条件:
keyはテンプレート変数の名前です。テンプレート変数名は、オプションで二重引用符(")で囲むことができます。valueはテンプレートの変数に割り当てる値です。文字列値は'または$$で囲む必要があります。例については、 テンプレート化の使用上の注意 をご参照ください。
DRY_RUN = { TRUE | FALSE }-
SQL スクリプトとして実行せずに、 レンダリングファイル をプレビューするかどうかを指定します。
TRUEは、 SQL ステートメントを実行せずに、レンダリングされたファイルのコンテンツを返します。FALSEは、テンプレートから SQL ステートメントをレンダリングし、それらのステートメントを実行します。
デフォルト:
FALSE
戻り値¶
EXECUTE IMMEDIATE FROM は次を返します。
すべてのステートメントが正常に実行された場合の、ファイルにある最後のステートメントの結果。
ファイル内のステートメントが失敗した場合のエラーメッセージ。
ファイル内のステートメントにエラーがある場合、 EXECUTE IMMEDIATE FROM コマンドは失敗し、失敗したステートメントのエラーメッセージが返されます。
注釈
EXECUTE IMMEDIATE FROM コマンドが失敗してエラーメッセージを返した場合、ファイル内の失敗したステートメントより前のステートメントは正常に完了しています。
アクセス制御の要件¶
EXECUTE IMMEDIATE FROM コマンドの実行に使用される ロール には、ファイルがあるステージに対する USAGE (外部ステージ)または READ (内部ステージ)権限が必要です。
ファイルの実行に使用されるロールは、そのロールが権限を持つファイル内のステートメントのみを実行することができます。たとえば、ファイル内に CREATE TABLE ステートメントがある場合、ロールにはアカウントに テーブルを作成するための必要な権限 が求められます。必要な権限がないと、ステートメントは失敗します。
Operating on an object in a schema requires at least one privilege on the parent database and at least one privilege on the parent schema.
指定された権限のセットを使用してカスタムロールを作成する手順については、 カスタムロールの作成 をご参照ください。
セキュリティ保護可能なオブジェクト に対して SQL アクションを実行するためのロールと権限付与に関する一般的な情報については、 アクセス制御の概要 をご参照ください。
使用上の注意¶
実行されるファイルの SQL ステートメントには、 EXECUTE IMMEDIATE FROM ステートメントを含めることができます。
絶対ファイルパスは、オプションで一重引用符(
')または$$で囲むことができます。実行するファイルのサイズは 10MB を超過することはできません。
実行するファイルは UTF-8 でエンコードする必要があります。
実行するファイルは解凍されている必要があります。PUT コマンドを使用して内部ステージにファイルをアップロードする場合は、 AUTO_COMPRESS パラメーター を明示的に FALSE に設定する必要があります。
たとえば、
my_file.sqlをmy_stageにアップロードします。PUT file://~/sql/scripts/my_file.sql @my_stage/scripts/ AUTO_COMPRESS=FALSE;
ディレクトリ内の全ファイルの実行はサポートされていません。例えば、
EXECUTE IMMEDIATE FROM @stage_name/scripts/はエラーになります。
テンプレート化の使用上の注意¶
テンプレート内の変数名は大文字と小文字を区別します。
オプションで、テンプレート変数名を二重引用符で囲むことができます。予約キーワード が変数名として使われている場合は、変数名を囲むと便利です。
USING 句では、以下のパラメーター型がサポートされています。
文字列。
'または$$で囲む必要があります。例:USING (a => 'a', b => $$b$$)。数値(10進数および整数)。例:
USING (a => 1, b => -1.23)。ブール値。例:
USING (a => TRUE, b => FALSE)。NULL。例:
USING (a => NULL)。注釈
Jinja2テンプレート化エンジンは NULL の値をPython NoneType の型として解釈します。
セッション変数。例:
USING (a => $var)。サポートされているデータ型の値を保持するセッション変数のみが許可されます。バインド変数。例:
USING (a => :var)。サポートされているデータ型の値を保持するバインド変数のみが許可されます。バインド変数を使用して、ストアドプロシージャの引数をテンプレートに渡すことができます。
Snowflake GitリポジトリやSnowflake Native Apps内のファイルには、テンプレートからアクセスできません。
現在、テンプレートレンダリングの最大結果サイズは 100.000 バイトです。
テンプレートはJinja2バージョン3.1.6のテンプレート化エンジンを使ってレンダリングされます。
EXECUTE IMMEDIATE FROM エラーのトラブルシューティング¶
このセクションには、 EXECUTE IMMEDIATE FROM ステートメントに起因する一般的なエラーと、その解決方法が含まれています。
ファイルエラー¶
エラー |
001501 (02000): File '<directory_name>' not found in stage '<stage_name>'.
|
|---|---|
原因 |
このエラーには複数の原因があります。
|
解決策 |
ファイル名を確認し、ファイルが存在することを確認します。ディレクトリ内の全ファイルの実行はサポートされていません。 |
エラー |
001503 (42601): Relative file references like '<filename.sql>' cannot be used in top-level EXECUTE IMMEDIATE calls.
|
|---|---|
原因 |
ファイル実行の外部で、相対ファイルパスを使用してステートメントが実行された。 |
解決策 |
相対ファイルパスは、ファイル内の EXECUTE IMMEDIATE FROM ステートメントでのみ使用できます。ファイル用に ファイルの絶対パス を使用します。詳細については、 使用上の注意 をご参照ください。 |
エラー |
001003 (42000): SQL compilation error: syntax error line <n> at position <m> unexpected '<string>'.
|
|---|---|
原因 |
ファイルに SQL 構文エラーがある。 |
解決策 |
ファイルの構文エラーを修正し、ステージにファイルを再アップロードします。 |
ステージエラー¶
エラー |
002003 (02000): SQL compilation error: Stage '<stage_name>' does not exist or not authorized.
|
|---|---|
原因 |
ステージが存在しないか、ステージにアクセスできない。 |
解決策 |
|
アクセス制御エラー¶
エラー |
003001 (42501): Uncaught exception of type 'STATEMENT_ERROR' in file <file_name> on line <n> at position <m>:
SQL access control error: Insufficient privileges to operate on schema '<schema_name>'
|
|---|---|
原因 |
ステートメントの実行に使用されたロールに、ファイル内のステートメントの一部またはすべてを実行するために必要な権限がない。 |
解決策 |
ファイル内のステートメントを実行するために適切な権限を持つロールを使用します。詳細については、 アクセス制御の要件 をご参照ください。 |
ステージエラー もご参照ください。
テンプレート化エラー¶
エラー |
001003 (42000): SQL compilation error:
syntax error line [n] at position [m] unexpected '{'.
|
|---|---|
原因 |
このファイルにはテンプレート化構造体(例: |
解決策 |
テンプレート化ディレクティブ を追加するか、 USING 句 を指定してステートメントを再実行し、少なくとも1つのテンプレート変数を指定します。 |
エラー |
000005 (XX000): Python Interpreter Error:
jinja2.exceptions.UndefinedError: '<key>' is undefined
in template processing
|
|---|---|
原因 |
テンプレートで使用される変数が USING 句で指定されていない場合は、エラーが発生します。 |
解決策 |
テンプレート内の変数の名前と数を確認し、 USING 句を更新して、すべてのテンプレート変数の値を含めます。 |
エラー |
001510 (42601): Unable to use value of template variable '<key>'
|
|---|---|
原因 |
変数 |
解決策 |
テンプレート変数の値にサポートされているパラメーター型が使用されていることを確認してください。詳細については、 テンプレート化の使用上の注意 をご参照ください。 |
エラー |
001518 (42601): Size of expanded template exceeds limit of 100,000 bytes.
|
|---|---|
原因 |
レンダリングされたテンプレートのサイズが現在の制限を超えています。 |
解決策 |
テンプレート化されたファイルを複数の小さなテンプレートに分割し、入れ子になったスクリプトにテンプレート変数を渡しながら、それらを順次実行する新しいスクリプトを追加します。 |
例¶
基本的な例¶
この例では、ステージ my_stage にあるファイル create-inventory.sql を実行します。
次のステートメントを使用して、
create-inventory.sqlという名前のファイルを作成します。CREATE OR REPLACE TABLE my_inventory( sku VARCHAR, price NUMBER ); EXECUTE IMMEDIATE FROM './insert-inventory.sql'; SELECT sku, price FROM my_inventory ORDER BY price DESC;
次のステートメントを使用して、
insert-inventory.sqlという名前のファイルを作成します。INSERT INTO my_inventory VALUES ('XYZ12345', 10.00), ('XYZ81974', 50.00), ('XYZ34985', 30.00), ('XYZ15324', 15.00);
内部ステージ
my_stageを作成します。CREATE STAGE my_stage;
PUT コマンドを使用して、両方のローカルファイルをステージにアップロードします。
PUT file://~/sql/scripts/create-inventory.sql @my_stage/scripts/ AUTO_COMPRESS=FALSE; PUT file://~/sql/scripts/insert-inventory.sql @my_stage/scripts/ AUTO_COMPRESS=FALSE;
my_stageのcreate-inventory.sqlスクリプトを実行します。EXECUTE IMMEDIATE FROM @my_stage/scripts/create-inventory.sql;
戻り値:
+----------+-------+ | SKU | PRICE | |----------+-------| | XYZ81974 | 50 | | XYZ34985 | 30 | | XYZ15324 | 15 | | XYZ12345 | 10 | +----------+-------+
簡単なテンプレート例¶
2つの変数とテンプレートディレクティブでテンプレートファイル
setup.sqlを作成します。--!jinja CREATE SCHEMA {{env}}; CREATE TABLE RAW (COL OBJECT) DATA_RETENTION_TIME_IN_DAYS = {{retention_time}};
ステージを作成する --- すでにファイルをアップロードできるステージがある場合は オプション です。
たとえば、Snowflakeに内部ステージを作成します。
CREATE STAGE my_stage;
ファイルをステージにコピーします。
たとえば、 PUT コマンドを使用して、ファイル
setup.sqlをローカル環境からステージmy_stageにアップロードします。PUT file://path/to/setup.sql @my_stage/scripts/ AUTO_COMPRESS=FALSE;
ファイル
setup.sqlを実行します。EXECUTE IMMEDIATE FROM @my_stage/scripts/setup.sql USING (env=>'dev', retention_time=>0);
マクロ、条件、ループ、インポートを含むテンプレートの例¶
マクロ定義を含むテンプレートファイルを作成します。
たとえば、ローカル環境に
macros.jinjaというファイルを作成します。{%- macro get_environments(deployment_type) -%} {%- if deployment_type == 'prod' -%} {{ "prod1,prod2" }} {%- else -%} {{ "dev,qa,staging" }} {%- endif -%} {%- endmacro -%}
テンプレートファイルを作成し、ファイルの先頭にテンプレートディレクティブ(
--!jinja2)を追加します。テンプレートディレクティブの後に、
importステートメントを追加して、前のステップで作成したファイルに定義されたマクロをインポートします。たとえば、ローカル環境にsetup-env.sqlというファイルを作成します。--!jinja2 {% from "macros.jinja" import get_environments %} {%- set environments = get_environments(DEPLOYMENT_TYPE).split(",") -%} {%- for environment in environments -%} CREATE DATABASE {{ environment }}_db; USE DATABASE {{ environment }}_db; CREATE TABLE {{ environment }}_orders ( id NUMBER, item VARCHAR, quantity NUMBER); CREATE TABLE {{ environment }}_customers ( id NUMBER, name VARCHAR); {% endfor %}
ステージを作成する --- すでにファイルをアップロードできるステージがある場合は オプション です。
たとえば、Snowflakeに内部ステージを作成します。
CREATE STAGE my_stage;
ファイルをステージにコピーします。
たとえば、
setup-env.sqlとmacros.jinjaのファイルをステージmy_stageにアップロードするには、内部環境から PUT コマンドを使用します。PUT file://path/to/setup-env.sql @my_stage/scripts/ AUTO_COMPRESS=FALSE; PUT file://path/to/macros.jinja @my_stage/scripts/ AUTO_COMPRESS=FALSE;
テンプレートによってレンダリングされた SQL ステートメントをプレビューして、Jinja2コードに問題がないか確認します。
EXECUTE IMMEDIATE FROM @my_stage/scripts/setup-env.sql USING (DEPLOYMENT_TYPE => 'prod') DRY_RUN = TRUE;
戻り値:
+----------------------------------+ | rendered file contents | |----------------------------------| | --!jinja2 | | CREATE DATABASE prod1_db; | | USE DATABASE prod1_db; | | CREATE TABLE prod1_orders ( | | id NUMBER, | | item VARCHAR, | | quantity NUMBER); | | CREATE TABLE prod1_customers ( | | id NUMBER, | | name VARCHAR); | | CREATE DATABASE prod2_db; | | USE DATABASE prod2_db; | | CREATE TABLE prod2_orders ( | | id NUMBER, | | item VARCHAR, | | quantity NUMBER); | | CREATE TABLE prod2_customers ( | | id NUMBER, | | name VARCHAR); | | | +----------------------------------+
ファイル
setup-env.sqlを実行します。EXECUTE IMMEDIATE FROM @my_stage/scripts/setup-env.sql USING (DEPLOYMENT_TYPE => 'prod');
