参数标记
参数标记是已命名的或未命名的类型化占位符变量,用于从调用 SQL 语句的 API 提供值。
使用参数标记可保护代码免受 SQL 注入攻击,因为它能够明确地将提供的值与 SQL 语句分开。
不能在同一 SQL 语句中混合已命名和未命名的参数标记。
不得在 DDL 语句(例如生成的列或 DEFAULT
定义、视图或 SQL 函数)中引用参数标记。
例外情况是对 IDENTIFIER
子句中的参数标记的引用,这些参数标记可用于参数化某些 DDL 语句中的表或列名称。 请参见 IDENTIFIER 子句。
可通过以下方式提供参数标记:
- 在 Python 中使用 pyspark.sql.SparkSession.sql() API。
- 在 Scala 中使用 org.apache.spark.sql.SparkSession.sql() API。
- Java 使用其 org.apache.spark.sql.SparkSession.sql() API。
已命名的参数标记
适用于:Databricks Runtime 12.1 及更高版本
已命名的参数标记是类型化占位符变量。 调用 SQL 语句的 API 必须提供名称/值对,以便将每个参数标记与值相关联。
语法
:parameter_name
参数
-
以非限定标识符的形式引用提供的参数标记。
说明
可以在同一 SQL 语句中多次引用同一参数标记。 如果没有任何值绑定到参数标记,则会引发 UNBOUND_SQL_PARAMETER 错误。 不需要引用所有提供的参数标记。
强制前置的 :
(冒号)将已命名的参数标记的命名空间与列名和 SQL 参数的命名空间区分开来。
示例
以下示例定义两个参数标记:
- later:值为 3 的
INTERVAL HOUR
。 - x:值为 15.0 的
DOUBLE
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 13.3 及更高版本
未命名的参数标记是类型化占位符变量。 调用 SQL 语句的 API 必须提供参数数组,以按参数标记的出现顺序将每个参数标记与值相关联。
语法
?
参数
?
:以问好标识符的形式引用提供的参数标记。
说明
每次出现未命名的参数标记时,都会使用 API 提供的值,按顺序调用 SQL 语句。 如果没有任何值绑定到参数标记,则会引发 UNBOUND_SQL_PARAMETER 错误。 不需要使用提供的所有值。
示例
以下示例定义 3 个参数标记:
- 一个
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|
// +------+