バインド変数

アプリケーションはユーザーからデータを受け取り、SQL ステートメントでそのデータを使用できます。たとえば、アプリケーションがユーザーに住所や電話番号などの連絡先情報の入力を求める場合があります。

このユーザー入力を SQL ステートメントで指定するには、ユーザー入力をステートメントの他の部分と連結して SQL ステートメントの文字列をプログラムで作成します。または、 バインド変数 を使用することもできます。変数をバインドするには、 SQL ステートメントのテキストに1つ以上のプレースホルダーを配置し、各プレースホルダーに変数(使用する値)を指定します。バインド変数を使用すると、ユーザー入力で SQL ステートメントを作成する際に SQL インジェクション攻撃を防ぐことができます。

Snowflakeでは、次の方法でバインド変数を使用できます。

概要

バインド変数を使うと、SQL ステートメントのリテラルをプレースホルダーに置き換えることができます。たとえば、次の SQL ステートメントでは、挿入値にリテラルを使用しています。

INSERT INTO t (c1, c2) VALUES (1, 'Test string');
Copy

次の SQL ステートメントでは、挿入値にプレースホルダーを使用しています。

INSERT INTO t (c1, c2) VALUES (?, ?);
Copy

アプリケーションコードは、SQL ステートメント内の各プレースホルダーとデータをバインドします。プレースホルダーでデータをバインドする手法は、プログラミング言語によって異なります。プレースホルダーの構文もプログラミング言語によって異なります。これは、 ?:<varname>%<varname> のいずれかです。

ドライバーでのバインド変数の使用

Snowflake ドライバー を使用すると、Snowflake上で操作を実行するアプリケーションを記述できます。ドライバーはGo、Java、Pythonなどのプログラミング言語をサポートしています。特定のドライバーのアプリケーションでバインド変数を使用する方法については、そのドライバーのリンクからご覧ください。

注釈

PHP ドライバーはバインド変数をサポートしていません。

Snowflakeスクリプトでのバインド変数の使用

Snowflakeスクリプトを使用して、コードブロックやストアドプロシージャなどの SQL を実行する手続き型コードを作成できます。変数名の前にコロンを付けます。たとえば、次の INSERT ステートメントは variable1 という名前のバインド変数を指定します。

INSERT INTO t (c1) VALUES (:variable1)
Copy

Snowflakeスクリプトでバインド変数を使用する情報については、 SQL ステートメントでの変数の使用(バインド) をご参照ください。

SQLAPI でのバインド変数の使用

Snowflake SQL REST API を使用して、Snowflakeデータベースのデータにアクセスして更新することができます。SQLAPI を使用するアプリケーションを作成して、 SQL ステートメントを送信し、展開を管理することができます。

SQL ステートメントを実行するリクエストを送信する場合、ステートメント内の値にバインド変数を使用できます。詳細については、 ステートメントでのバインド変数の使用 をご参照ください。

変数に対する値の配列のバインド

SQL ステートメントでは、値の配列を変数にバインドできます。この手法を使用すると、1つのバッチで複数行を挿入することで、ネットワークのラウンドトリップやコンパイルを回避し、パフォーマンスを向上させることができます。配列バインドの使用は、「バルクインサート」または「バッチインサート」とも呼ばれます。

注釈

Snowflakeは、配列バインドの使用の代わりに推奨される他のデータロード方法をサポートしています。詳細については、 Snowflakeにデータをロードする および データのロードおよびアンロードコマンド をご参照ください。

以下は、Pythonコードでの配列バインドの例です。

conn = snowflake.connector.connect( ... )
rows_to_insert = [('milk', 2), ('apple', 3), ('egg', 2)]
conn.cursor().executemany(
             "insert into grocery (item, quantity) values (?, ?)",
             rows_to_insert)
Copy

この例では、次のバインドリストを指定します: [('milk', 2), ('apple', 3), ('egg', 2)]。アプリケーションがバインドリストを指定する方法は、プログラミング言語によって異なります。

このコードは、テーブルに3行を挿入します。

+-------+----+
| C1    | C2 |
|-------+----|
| milk  |  2 |
| apple |  3 |
| egg   |  2 |
+-------+----+

特定のドライバーのアプリケーションで配列バインドを使用する方法については、そのドライバーのリンクからご覧ください。

注釈

PHP ドライバーは配列バインドをサポートしていません。

配列バインドの制限事項

配列バインドには、次の制限が適用されます。

  • 配列バインド変数を含むことができるのは INSERT INTO... VALUES ステートメントだけです。

  • VALUES 句は、バインド変数の単一行リストでなければなりません。たとえば、次の VALUES 句は許可されていません。

    VALUES (?,?), (?,?)
    
    Copy

配列バインドを使用しない複数行の挿入

INSERT ステートメントでは、バインド変数を使用して、配列バインドを使用せずに複数行を挿入することができます。次の例では、2つの行に値を挿入していますが、配列バインドは使用していません。

INSERT INTO t VALUES (?,?), (?,?);
Copy

アプリケーションは、プレースホルダーに次の値を順番に並べたものと等しいバインドリストを指定することができます: [1,'String1',2,'String2']。VALUES 句は複数行を指定するので、ステートメントは動的な行数ではなく、正確な値の数(例では4つ)のみを挿入します。

半構造化データでのバインド変数の使用

半構造化データを変数にバインドするには、変数を文字列型としてバインドし、 PARSE_JSONARRAY_CONSTRUCT のような関数を使用します。

次の例では、 VARIANT 列を1つ持つテーブルを作成し、 PARSE_JSON 関数を呼び出してバインド変数で半構造化データをテーブルに挿入します。

CREATE TABLE t (a VARIANT);
-- Code that supplies a bind value for ? of '{'a': 'abc', 'x': 'xyz'}'
INSERT INTO t SELECT PARSE_JSON(a) FROM VALUES (?);
Copy

次の例では、テーブルにクエリを行います。

SELECT * FROM t;
Copy

クエリは次の出力を返します。

+---------------+
| A             |
|---------------|
| {             |
|   "a": "abc", |
|   "x": "xyz"  |
| }             |
+---------------+

次のステートメントは、 ARRAY_CONSTRUCT 関数を呼び出して、バインド変数を持つ VARIANT 列に半構造化データの配列を挿入します。

INSERT INTO t SELECT ARRAY_CONSTRUCT(column1) FROM VALUES (?);
Copy

これらの例はどちらも単一行を挿入することができますが、配列バインドを使用して複数行を1つのバッチで挿入することもできます。この手法を使って、 VARIANT 列に有効な任意のタイプの半構造化データを挿入することができます。