パラメーター マーカー

パラメーター マーカーは、SQL ステートメントを呼び出す API から値を供給するために使用される名前付きまたは名前のない型指定付きプレースホルダー変数です。

パラメーター マーカーを使用すると、指定された値が SQL ステートメントから明確に分離されるため、SQL インジェクション攻撃からコードが保護されます。

名前付きパラメーター マーカーと名前のないパラメーター マーカーを同じ SQL ステートメント内に混在させることはできません。

生成される列や DEFAULT 定義、ビュー、SQL 関数などの DDL ステートメントでパラメーター マーカーを参照することはできません。

例外は、特定の DDL ステートメントでテーブル名または列名をパラメーター化するのに使用できる IDENTIFIER 句内のパラメーター マーカーへの参照です。 「IDENTIFIER 句」を参照してください。

パラメーター マーカーは、次の方法で指定できます。

名前付きパラメーター マーカー

適用対象: Databricks Runtime check marked yes 12.1 以降

名前付きパラメーター マーカーは、型指定付きのプレースホルダー変数です。 SQL ステートメントを呼び出す API は、各パラメーター マーカーを値に関連付ける名前と値のペアを指定する必要があります。

構文

 :parameter_name

パラメーター

  • named_parameter_name

    修飾されていない識別子の形式で指定されるパラメーター マーカーへの参照。

メモ

同じ SQL ステートメント内で同じパラメーター マーカーを複数回参照できます。 パラメーター マーカーに値がバインドされていない場合は、UNBOUND_SQL_PARAMETER エラーが発生します。 指定されたすべてのパラメーター マーカーを参照する必要はありません。

必須の先頭の : (コロン) は、名前付きパラメーター マーカーの名前空間を列名および SQL パラメーターの名前空間と区別します。

次の例では、2 つのパラメーター マーカーを定義しています。

  • later: 値が 3 の INTERVAL HOUR
  • x: 値が 15.0 の DOUBLE

x は複数回参照され、later は 1 回参照されます。

SQL

> DECLARE stmtStr = 'SELECT current_timestamp() + :later, :x * :x AS square';
> EXECUTE IMMEDIATE stmtStr USING INTERVAL '3' HOURS AS later, 15.0 AS x;
  2024-01-19 16:17:16.692303  225.00

Scala

import org.apache.spark.sql.SparkSession

val spark = SparkSession
  .builder()
  .appName("Spark named parameter marker example")
  .getOrCreate()

val argMap = Map("later" -> java.time.Duration.ofHours(3), "x" -> 15.0)
spark.sql(
  sqlText = "SELECT current_timestamp() + :later, :x * :x AS square",
  args = argMap).show()
// +----------------------------------------+------+
// |current_timestamp() + INTERVAL '03' HOUR|square|
// +----------------------------------------+------+
// |                    2023-02-27 17:48:...|225.00|
// +----------------------------------------+------+

Java

import org.apache.spark.sql.*;
import static java.util.Map.entry;

SparkSession spark = SparkSession
  .builder()
  .appName("Java Spark named parameter marker example")
  .getOrCreate();

Map<String, String> argMap = Map.ofEntries(
  entry("later", java.time.Duration.ofHours(3)),
  entry("x", 15.0)
);

spark.sql(
  sqlText = "SELECT current_timestamp() + :later, :x * :x AS square",
  args = argMap).show();
// +----------------------------------------+------+
// |current_timestamp() + INTERVAL '03' HOUR|square|
// +----------------------------------------+------+
// |                    2023-02-27 17:48:...|225.00|
// +----------------------------------------+------+

Python

spark.sql("SELECT :x * :y * :z AS volume", args = { "x" : 3, "y" : 4, "z"  : 5 }).show()
// +------+
// |volume|
// +------+
// |    60|
// +------+

名前のないパラメーター マーカー

適用対象: Databricks Runtime check marked yes 13.3 以降

名前のないパラメーター マーカーは、型指定付きのプレースホルダー変数です。 SQL ステートメントを呼び出す API は、各パラメーター マーカーを出現順に値に関連付ける引数の配列を指定する必要があります。

構文

 ?

パラメーター

  • ?: 疑問符の形式で指定されたパラメーター マーカーへの参照。

メモ

名前のないパラメーター マーカーが出現するたびに、SQL ステートメントを順番に呼び出す API によって提供される値が使用されます。 パラメーター マーカーに値がバインドされていない場合は、UNBOUND_SQL_PARAMETER エラーが発生します。 指定されたすべての値を使用する必要はありません。

次の例では、3 つのパラメーター マーカーを定義しています。

  • 値 が 3 の 1つの INTERVAL HOUR
  • 値 が 15.0 の 2 つの DOUBLE

パラメーターに名前がないため、指定された各値は最大 1 つのパラメーターによって使用されます。

SQL

> DECLARE stmtStr = 'SELECT current_timestamp() + ?, ? * ? AS square';
> EXECUTE IMMEDIATE stmtStr USING INTERVAL '3' HOURS, 15.0, 15.0;
  2024-01-19 16:17:16.692303  225.00

Scala

import org.apache.spark.sql.SparkSession

val spark = SparkSession
  .builder()
  .appName("Spark unnamed parameter marker example")
  .getOrCreate()

val argArr = Array(java.time.Duration.ofHours(3), 15.0, 15.0)

spark.sql(
  sqlText = "SELECT current_timestamp() + ?, ? * ? AS square", args = argArr).show()
// +----------------------------------------+------+
// |current_timestamp() + INTERVAL '03' HOUR|square|
// +----------------------------------------+------+
// |                    2023-02-27 17:48:...|225.00|
// +----------------------------------------+------+

Java

import org.apache.spark.sql.*;

SparkSession spark = SparkSession
  .builder()
  .appName("Java Spark unnamed parameter marker example")
  .getOrCreate();

Object[] argArr = new Object[] { java.time.Duration.ofHours(3), 15.0, 15.0 }

spark.sql(
  sqlText = "SELECT current_timestamp() + ?, ? * ? AS square",
  args = argArr).show();
// +----------------------------------------+------+
// |current_timestamp() + INTERVAL '03' HOUR|square|
// +----------------------------------------+------+
// |                    2023-02-27 17:48:...|225.00|
// +----------------------------------------+------+

Python

spark.sql("SELECT ? * ? * ? AS volume", args = { 3, 4, 5 }).show()
// +------+
// |volume|
// +------+
// |    60|
// +------+