Маркеры параметров

Область применения:Отмечено «Да» Databricks SQL Отмечено «Да» Databricks Runtime

Маркеры параметров — это именованные или неименованные типизированные переменные-заполнители, которые используются для предоставления значений из API, вызывающего SQL-инструкцию.

Использование маркеров параметров защищает код от атак внедрения SQL, так как он четко отделяет предоставленные значения от структуры инструкций SQL.

Маркеры именованных и неименованных параметров нельзя смешивать в той же инструкции SQL.

Маркеры параметров также можно использовать в IDENTIFIER предложении, которые можно использовать для параметризации имен объектов. См. пункты IDENTIFIER.

Маркеры параметров могут быть предоставлены следующими способами:

Применяются следующие правила:

  • Область применения:отмечено да Databricks SQL отмечено да Databricks Runtime 17.3 LTS и более ранние версии

    • Вы можете ссылаться на маркер параметра в выражении
    • Не следует ссылаться на маркер параметра в инструкции DDL, например в случае с созданным столбцом, определением DEFAULT, представлением или функцией SQL. Исключения — это ссылки на маркеры параметров в IDENTIFIER предложении, которые можно использовать для параметризации темы определенных инструкций DDL. См. пункты IDENTIFIER.
  • Область применения:помечено «да» Databricks Runtime 18.0 и более поздних версий

    • Вы можете ссылаться на маркер параметра везде, где можно использовать литерал типа маркера параметра. Это отменяет предыдущее ограничение DDL, разрешая маркеры параметров в созданных столбцах, определениях, DEFAULT представлениях, функциях SQL и предложениях DDL с строковым значением, например LOCATION.

Именованные маркеры параметров

применимо: Databricks Runtime отмечено 12.1 и более поздних версий

Именованные маркеры параметров это типизированные переменные-заполнители. API, вызывающий инструкцию SQL, должен предоставлять пары "имя-значение", чтобы связать каждый маркер параметра со значением.

Синтаксис

 :parameter_name

Параметры

  • named_parameter_name

    Ссылка на предоставленный маркер параметра в виде некавалифицированного идентификатора.

Примечания

Один и тот же маркер параметров можно ссылаться несколько раз в одной инструкции SQL. Если значение не было привязано к маркеру параметра, возникает ошибка UNBOUND_SQL_PARAMETER. Вам не требуется ссылаться на все предоставленные маркеры параметров.

Обязательный предшествующий символ : (двоеточие) отличает пространство имен для именованных параметров от имен столбцов и параметров SQL.

Примеры

В следующем примере определяются два маркера параметров:

  • позже: INTERVAL HOUR со значением 3.
  • x: DOUBLE со значением 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|
// +----------------------------------------+------+

Ява

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

Питон

spark.sql("SELECT current_timestamp() + :later, :x * :x AS square",
  args = { "later": datetime.timedelta(hours=3), "x": 15.0 }).show()
// +----------------------------------------+------+
// |current_timestamp() + INTERVAL '03' HOUR|square|
// +----------------------------------------+------+
// |                    2023-02-27 17:48:...|225.00|
// +----------------------------------------+------+

Применимо к: Проверка среды выполнения Databricks помечена как да 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 и более поздним версиям

Обозначения безымянных параметров являются типизированными переменными-шаблонами. API, вызывающий инструкцию SQL, должен предоставить массив аргументов, чтобы связать каждый маркер параметра со значением в порядке, в котором они отображаются.

Синтаксис

 ?

Параметры

  • ?: Ссылка на предоставленный маркер параметра в виде вопросительного знака.

Примечания

Каждое вхождение маркера неназванного параметра использует значение, предоставленное 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|
// +----------------------------------------+------+

Ява

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

Питон

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

Применимо к: Проверка среды выполнения Databricks помечена как да 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, 'comment';

Маркеры параметров в предложениях строк DDL

Некоторые предложения DDL, такие как LOCATION предложение, CREATE TABLEпринимают строковые литералы, а не идентификаторы. Не удается использовать IDENTIFIER предложение для этих предложений, так как они не являются именами объектов.

Применимо к: Проверка среды выполнения Databricks помечена как да 18.0 и выше

В Databricks Runtime 18.0 и более поздних версиях можно использовать маркеры параметров непосредственно в этих предложениях, так как Databricks Runtime поддерживает маркеры параметров, где бы он ни принимал литерал одного типа. Рассмотрим пример.

SQL

> CREATE EXTERNAL TABLE my_table USING DELTA LOCATION :path;

Питон

spark.sql(
  "CREATE EXTERNAL TABLE my_table USING DELTA LOCATION :path",
  args = {"path": "abfss://container@account.dfs.core.windows.net/data"})

Scala

val argMap = Map("path" -> "abfss://container@account.dfs.core.windows.net/data")
spark.sql(
  sqlText = "CREATE EXTERNAL TABLE my_table USING DELTA LOCATION :path",
  args = argMap)

Ява

Map<String, String> argMap = Map.ofEntries(
  entry("path", "abfss://container@account.dfs.core.windows.net/data")
);

spark.sql(
  sqlText = "CREATE EXTERNAL TABLE my_table USING DELTA LOCATION :path",
  args = argMap);

Для версий среды выполнения Databricks до 18.0

Область применения:check помечена да проверка Databricks SQL помечается да Databricks Runtime 14.3 до 17.3 LTS

В версиях до Databricks Runtime 18.0 databricks Runtime не разрешает маркеры параметров непосредственно в инструкциях DDL (за исключением предложения IDENTIFIER ). Для динамической сборки инструкции SQL можно EXECUTE IMMEDIATE объединить значение пути в виде строкового литерала:

> DECLARE path STRING DEFAULT 'abfss://container@account.dfs.core.windows.net/data';
> EXECUTE IMMEDIATE 'CREATE EXTERNAL TABLE my_table USING DELTA LOCATION \'' || path || '\'';

Note

Невозможно внедрить маркер параметра в строковый литерал (например, 'abfss://:param/path'). Вместо этого перед передачей значения перед передачей значения перед передачей всей строки перед передачей следует передать всю строку в виде одного параметра или использовать объединение строк. Например, используйте для SET VARIABLECONCAT() создания полного пути в переменной, а затем передайте переменную EXECUTE IMMEDIATEв .