参数标记

适用于:勾选“是” Databricks SQL 勾选“是” Databricks Runtime

参数标记是 命名未命名 的类型占位符变量,用于从调用 SQL 语句的 API 提供值。

使用参数标记可保护代码免受 SQL 注入攻击,因为它清楚地将提供的值与 SQL 语句的结构分开。

不能在同一 SQL 语句中混合命名和未命名的参数标记。

还可以在 IDENTIFIER 子句中使用参数标记,这些标记可用于参数化 对象名称。 请参阅 IDENTIFIER 子句

可以通过以下方法提供参数标记:

下列规则适用:

  • 适用于:勾选为“是”的 Databricks SQL 勾选为“是”的 Databricks Runtime 17.3 LTS 及更早版本

    • 可以在表达式中引用参数标记
    • 不得引用 DDL 语句中的参数标记,例如生成的列或 DEFAULT 定义、视图或 SQL 函数。 例外是对IDENTIFIER子句中的参数标记的引用,它们可用于对某些DDL语句的主题进行参数化。 请参阅 IDENTIFIER 子句
  • 适用于:选中“是” Databricks Runtime 18.0 及更高版本

    • 你可以在可以使用参数标记类型的字面值的任何地方引用参数标记。

命名参数标记

适用于: Databricks Runtime 打勾标记为“是” 12.1及更高版本

命名参数标记是类型化的占位符变量。 调用 SQL 语句的 API 必须提供名称/值对,以便将每个参数标记与一个值相关联。

Syntax

 :parameter_name

参数

注释

可以在同一 SQL 语句中多次引用相同的参数标记。 如果没有值绑定到参数标记,则会引发 UNBOUND_SQL_PARAMETER 错误。 无需引用所有提供的参数标记。

前面的必需 :(冒号)用于区分命名参数标记的命名空间与列名称和 SQL 参数的命名空间。

例子

以下示例定义了两个参数标记:

  • 稍后: 一个值为 3 的 INTERVAL HOUR
  • x:值为 15.0 的 A 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 检查标记为是 18.0 及更高版本

> EXECUTE IMMEDIATE 'SELECT 1::DECIMAL(:precision, :scale)' USING 6 AS precision, 4 AS scale;
  1.0000

> EXECUTE IMMEDIATE 'CREATE VIEW v(c1 INT) AS SELECT :val AS c1' USING 10 AS val;
> SELECT * FROM v;
  10

> EXECUTE IMMEDIATE 'CREATE TABLE T(c1 INT DEFAULT :def COMMENT \'This is a \' :com)' USING 17 AS def, 'comment' as com;

未命名的参数标记

适用于: Databricks Runtime 检查标记为“是 ”13.3 及更高版本

未命名的参数标记是类型化的占位符变量。 调用 SQL 语句的 API 必须提供一个参数数组,以便将每个参数标记与它们的显示顺序中的值相关联。

Syntax

 ?

参数

  • ?:对提供的参数标记的引用,格式为问号。

注释

每个未命名参数标记都会顺序使用 API 提供给 SQL 语句的值。 如果未将值绑定到参数标记,则会引发 UNBOUND_SQL_PARAMETER 错误。 无需使用所有提供的值。

例子

以下示例定义了三个参数标记:

  • 一个值为 3 的 INTERVAL HOUR
  • 两个 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|
// +------+

适用于: Databricks Runtime 检查标记为是 18.0 及更高版本

> EXECUTE IMMEDIATE 'SELECT 1::DECIMAL(?, ?)' USING 6, 4;
  1.0000

> EXECUTE IMMEDIATE 'CREATE VIEW v(c1 INT) AS SELECT ? AS c1' USING 10;
> SELECT * FROM v;
  10

> EXECUTE IMMEDIATE 'CREATE TABLE T(c1 INT DEFAULT ? COMMENT \'This is a \' ?)' USING 17 AS def, ? as com;