參數標記

參數標記是 命名未命名的具型別 佔位元元變數,用來從叫用 SQL 語句的 API 提供值。

使用參數標記可保護您的程式代碼免於遭受 SQL 插入式攻擊,因為它會清楚地分隔提供的 SQL 語句值。

您無法在相同的 SQL 語句中混合具名和未命名的參數標記。

您不得參考 DDL 語句中的參數標記,例如產生的數據行或 DEFAULT 定義、檢視或 SQL 函式。

例外狀況是 子句中參數標記的 IDENTIFIER 參考,可用來將特定 DDL 語句中的數據表或數據行名稱參數化。 請參閱 IDENTIFIER子句

參數標記可以透過:

具名參數標記

適用於: Databricks Runtime check marked yes 12.1 和更新版本

具名參數標記是具類型的佔位元變數。 叫用 SQL 語句的 API 必須提供名稱/值組,讓每個參數標記與值產生關聯。

語法

 :parameter_name

參數

備註

您可以在相同的 SQL 語句內多次參考相同的參數標記。 如果沒有值系結至參數標記,就會 引發UNBOUND_SQL_PARAMETER 錯誤。 您不需要參考所有提供的參數標記。

前一個強制 : 的 (冒號) 會區分具名參數標記的命名空間與數據行名稱和 SQL 參數的命名空間。

範例

下列範例會定義兩個參數標記:

  • 稍後INTERVAL HOUR 值為 3 的 。
  • xDOUBLE 值為 15.0 的

x 會多次參考,而 later 會參考一次。

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 必須提供自變數陣列,以便讓每個參數標記與其出現的順序產生關聯。

語法

 ?

參數

  • ?:以問號形式提供之參數標記的參考。

備註

每次出現未命名的參數標記都會取用 API 依序叫用 SQL 語句所提供的值。 如果沒有值系結至參數標記, 則會引發UNBOUND_SQL_PARAMETER 錯誤。 您不需要取用所有提供的值。

範例

下列範例會定義三個參數標記:

  • INTERVAL HOUR值為 3 的 。
  • DOUBLE 個,每個值 15.0。

因為參數未命名,每個提供的值最多都會由一個參數取用。

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|
// +------+