Marcadores de parámetros

Se aplica a:casilla marcada como Sí Databricks SQL casilla marcada como Sí Databricks Runtime

Los marcadores de parámetro se denominan o las variables de marcador de posición con tipo sin nombre que se usan para proporcionar valores de la API que invocan la instrucción SQL.

El uso de marcadores de parámetros protege el código de los ataques por inyección de código SQL, ya que separa claramente los valores proporcionados de la estructura de las instrucciones SQL.

No se pueden mezclar marcadores de parámetros con nombre y sin nombre en la misma instrucción SQL.

También puede usar marcadores de parámetros en la IDENTIFIER cláusula , que se puede usar para parametrizar nombres de objeto. Consulta la cláusula IDENTIFIER.

Los marcadores de parámetros se pueden proporcionar mediante:

Se aplican las reglas siguientes:

  • Se aplica a:marcado como sí Databricks SQL marcado como sí Databricks Runtime 17.3 LTS y anteriores

    • Puede hacer referencia a un marcador de parámetros en una expresión.
    • No debe hacer referencia a un marcador de parámetro en una instrucción DDL, como una columna generada o una definición de DEFAULT, una vista o una función SQL. Las excepciones son referencias a marcadores de parámetros en la IDENTIFIER cláusula, que se pueden usar para parametrizar el tema de ciertas instrucciones DDL. Consulta la cláusula IDENTIFIER.
  • Se aplica a:marcado como sí Databricks Runtime 18.0 y versiones posteriores

    • Puede hacer referencia a un marcador de parámetros siempre que pueda usar un literal del tipo del marcador de parámetro. Esto eleva la restricción DDL anterior, lo que permite marcadores de parámetro en columnas generadas, DEFAULT definiciones, vistas, funciones SQL y cláusulas DDL con valores de cadena, como LOCATION.

Marcadores de parámetros con nombre

Se aplica a: Databricks Runtime marcado como sí 12.1 y versiones posteriores

Los marcadores de parámetro con nombre son variables de marcador de posición con tipo. La API que invoca la instrucción SQL debe proporcionar pares nombre-valor para asociar cada marcador de parámetro a un valor.

Sintaxis

 :parameter_name

Parámetros

  • named_parameter_name

    Referencia a un marcador de parámetro proporcionado en forma de identificador no calificado.

Notas

Puede hacer referencia al mismo marcador de parámetro varias veces dentro de la misma instrucción SQL. Si no se ha enlazado ningún valor al marcador de parámetro, se produce un error de UNBOUND_SQL_PARAMETER. No es necesario hacer referencia a todos los marcadores de parámetro proporcionados.

El precedente obligatorio : (dos puntos) diferencia el espacio de nombres de los marcadores de parámetro con nombre de los nombres de columna y los parámetros SQL.

Ejemplos

En el ejemplo siguiente se definen dos marcadores de parámetro:

  • más adelante: un INTERVAL HOUR con el valor 3.
  • x: un DOUBLE con el valor 15.0

x se hace referencia varias veces, mientras que se hace referencia a later una vez.

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

Pitón

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

Se aplica a: Comprobación en tiempo de ejecución de Databricks marcada como sí 18.0 y versiones posteriores

> 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;

Marcadores de parámetro sin nombre

Se aplica a: Databricks Runtime marcado como sí 13.3 y versiones posteriores

Los marcadores de parámetro sin nombre son variables de marcador de posición con tipo. La API que invoca la instrucción SQL debe proporcionar una matriz de argumentos para asociar cada marcador de parámetro a un valor en el orden en que aparecen.

Sintaxis

 ?

Parámetros

  • ?: referencia a un marcador de parámetro proporcionado en forma de signo de interrogación.

Notas

Cada aparición de un marcador de parámetro sin nombre consume un valor proporcionado por la API que invoca la instrucción SQL en orden. Si no se ha enlazado ningún valor al marcador de parámetros, se genera un error UNBOUND_SQL_PARAMETER. No es necesario consumir todos los valores proporcionados.

Ejemplos

En el ejemplo siguiente se definen tres marcadores de parámetro:

  • Un INTERVAL HOUR con el valor 3.
  • Dos DOUBLE con el valor 15,0 cada uno.

Dado que los parámetros no tienen nombre, cada valor proporcionado se consume como máximo en un parámetro.

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

Pitón

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

Se aplica a: Comprobación en tiempo de ejecución de Databricks marcada como sí 18.0 y versiones posteriores

> 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';

Marcadores de parámetro en cláusulas de cadena DDL

Algunas cláusulas DDL, como la LOCATION cláusula de CREATE TABLE, aceptan literales de cadena en lugar de identificadores. No se puede usar la IDENTIFIER cláusula para estas cláusulas porque no son nombres de objeto.

Se aplica a: Comprobación en tiempo de ejecución de Databricks marcada como sí 18.0 y versiones posteriores

En Databricks Runtime 18.0 y versiones posteriores, puede usar marcadores de parámetros directamente en estas cláusulas porque Databricks Runtime admite marcadores de parámetros donde acepte un literal del mismo tipo. Por ejemplo:

SQL

> CREATE EXTERNAL TABLE my_table USING DELTA LOCATION :path;

Pitón

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)

Java

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);

Para las versiones de Databricks Runtime anteriores a la 18.0

Se aplica a:check marcado yes Databricks SQL check marcado yes Databricks Runtime 14.3 a 17.3 LTS

En versiones anteriores a Databricks Runtime 18.0, Databricks Runtime no permite marcadores de parámetros directamente en instrucciones DDL (excepto a través de la IDENTIFIER cláusula ). Puede usar EXECUTE IMMEDIATE para compilar la instrucción SQL dinámicamente, concatenando el valor de ruta de acceso como un literal de cadena:

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

Note

No se puede insertar un marcador de parámetro dentro de un literal de cadena (por ejemplo, 'abfss://:param/path'). En su lugar, pase toda la cadena como un único parámetro o use la concatenación de cadenas para compilar el valor antes de pasarla. Por ejemplo, use SET VARIABLE con CONCAT() para compilar la ruta de acceso completa en una variable y, a continuación, pase la variable a EXECUTE IMMEDIATE.