Comparteix a través de


Resolución de nombres

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

La resolución de nombres es el proceso por el que los identificadores se resuelven como referencias de columna, campo, parámetro o tabla específicas.

Resolución de columnas, campos, parámetros y variables

Los identificadores de las expresiones pueden ser referencias a cualquiera de los siguientes elementos:

La resolución de nombres aplica los siguientes principios:

  • Gana la mejor coincidencia.
  • Las columnas y los parámetros ganan por encima de los campos y las claves.

En detalle, la resolución de identificadores como una referencia específica sigue estas reglas en orden:

  1. Referencias locales

    1. Referencia de columna

      Busca una coincidencia del identificador, que puede estar completo, con un nombre de columna en una referencia de tabla de FROM clause.

      Si hay más de una coincidencia, genera el error AMBIGUOUS_COLUMN_OR_FIELD.

    2. Referencia de función sin parámetros

      Si el identificador no está completo y coincide con current_user, current_date o current_timestamp, lo resuelve como una de estas funciones.

    3. Especificación de columna DEFAULT

      Si el identificador no está completo, coincide con default y compone toda la expresión en el contexto de UPDATE SET, INSERT VALUESo MERGE WHEN [NOT] MATCHED, lo resuelve como el valor DEFAULT de la tabla de destino correspondiente a INSERT, UPDATE o MERGE.

    4. Referencia de campo de estructura o clave de asignación

      Si el identificador está completo, busca una coincidencia con un campo o una clave de asignación según los pasos siguientes:

      Un. Quita el último identificador y lo trata como un campo o una clave. B. Busca una coincidencia del resto con una columna de la referencia de tabla o de FROM clause.

      Si hay más de una coincidencia, genera el error AMBIGUOUS_COLUMN_OR_FIELD.

      Si hay una coincidencia y la columna es:

      • STRUCT: establece la coincidencia con el campo.

        Si no puede establecer una coincidencia con el campo, genera el error FIELD_NOT_FOUND.

        Si hay más de un campo, genera el error AMBIGUOUS_COLUMN_OR_FIELD.

      • MAP: genera un error si la clave está completa.

        Puede producirse un error en tiempo de ejecución si la clave no está presente realmente en el mapa.

      • Cualquier otro tipo: genera un error. C. Repita el paso anterior para quitar el identificador final como un campo. Aplique las reglas (A) y (B) mientras quede un identificador para interpretarlo como una columna.

  2. Alias de columna lateral

    Se aplica a:casilla marcada como sí Databricks SQL casilla marcada como Sí Databricks Runtime 12.2 LTS y versiones posteriores

    Si la expresión está dentro de una lista SELECT, haga coincidir el identificador inicial con un alias de columna anterior en esa lista SELECT.

    Si hay más de una coincidencia de ese tipo, genera el error AMBIGUOUS_LATERAL_COLUMN_ALIAS.

    Busca una coincidencia del resto del identificador con un campo o una clave de asignación y genera el error FIELD_NOT_FOUND o AMBIGUOUS_COLUMN_OR_FIELD si no puede establecer una coincidencia.

  3. Correlación

    • LATERAL

      Si la consulta va precedida de una palabra clave LATERAL, aplica las reglas 1.a y 1.d teniendo en cuenta las referencias de tabla de FROM que contienen la consulta y preceden a LATERAL.

    • Regular

      Si la consulta es una subconsulta escalar, una IN, o una EXISTS subconsulta, aplique las reglas 1.a, 1.d y 2 teniendo en cuenta las referencias de tabla en la cláusula FROM de la consulta contenedora.

  4. Correlación anidada

    Vuelve a aplicar la regla 3 iterándola en los niveles de anidamiento de la consulta.

  5. Bucle FOR

    Si la instrucción está contenida en un FOR bucle:

    Un. Asigna el identificador a una columna en una consulta en un bucle de instrucciones. Si el identificador está calificado, el calificador debe coincidir con el nombre de la variable de bucle FOR si se define. B. Si el identificador está completo, busca una coincidencia con un campo o una clave de asignación de un parámetro siguiendo la regla 1.c.

  6. Instrucción compuesta

    Si la instrucción está contenida en una instrucción compuesta:

    Un. Coincide el identificador con una variable declarada en la instrucción compuesta. Si el identificador está calificado, el calificador debe coincidir con la etiqueta de la instrucción compuesta si se ha definido. B. Si el identificador está completo, busque una coincidencia con un campo o una clave de asignación de una variable siguiendo la regla 1.c

  7. Bucle o FOR instrucción compuesta anidada

    Vuelva a aplicar las reglas 5 y 6, iterando sobre los niveles de anidamiento de la instrucción compuesta.

  8. Parámetros de rutina

    Si la expresión forma parte de una CREATE FUNCTION instrucción CREATE PROCEDURE:

    1. Busca una coincidencia del identificador con un nombre de parámetro. Si el identificador está calificado, el calificador debe coincidir con el nombre de la rutina.
    2. Si el identificador está completo, busca una coincidencia con un campo o una clave de asignación de un parámetro siguiendo la regla 1.c.
  9. Variables de sesión

    1. Haga coincidir el identificador con un nombre de variable. Si el identificador está calificado, el calificador debe ser session o system.session.
    2. Si el identificador está completo, busque una coincidencia con un campo o una clave de asignación de una variable siguiendo la regla 1.c

Resolución de nombres en HAVING, ORDER BYy QUALIFY

Las HAVINGcláusulas , ORDER BYy QUALIFY pueden hacer referencia a nombres de la SELECT lista, así como columnas de las tablas subyacentes. Cuando un nombre de una de estas cláusulas coincide con un alias de columna en la SELECT lista y una columna de tabla, las cláusulas resuelven la ambigüedad de forma diferente:

  • ORDER BY prefiere el alias de SELECT lista sobre la columna de tabla.
  • HAVING prefiere la columna de tabla sobre el alias de SELECT lista.
  • QUALIFY prefiere la columna de tabla sobre el SELECT alias de lista (igual que HAVING).

Ejemplos

> CREATE OR REPLACE TEMPORARY VIEW t(a, b) AS VALUES (1, 10), (2, 20), (3, 30);

-- ORDER BY prefers the alias over the column.
-- 'a' in ORDER BY refers to the alias (-a), not column 'a',
-- so the row with the largest column 'a' comes first.
> SELECT -a AS a FROM t ORDER BY a LIMIT 1;
  -3

-- HAVING prefers the column over the alias.
-- 'a' in HAVING refers to column 'a', not the alias sum(b).
> SELECT sum(b) AS a FROM t GROUP BY a HAVING a > 1;
  20
  30

-- QUALIFY prefers the column over the alias (same as HAVING).
-- 'a' in QUALIFY refers to column 'a', not the alias -row_number().
> SELECT -row_number() OVER (ORDER BY b) AS a FROM t QUALIFY a > 1;
  -2
  -3

Prioridad de extracción de campos y resolución de nombres

Cuando se usa un nombre completo como a.b en HAVING o ORDER BY, las reglas de prioridad anteriores se siguen aplicando, pero con una consideración adicional: el candidato preferido debe admitir la extracción de claves de mapa o campo de estructura. Si no es así, se usa el otro candidato en su lugar.

Por ejemplo, si el alias a se resuelve en una columna sin formato INT , pero la columna a de tabla es un STRUCT con campo x, ORDER BY elige la STRUCT columna porque un campo no se puede extraer del INT alias. Por el contrario, si la columna de tabla es sin formato INT y el alias es , STRUCTHAVING vuelve al alias para la extracción de campos.

Ejemplos

-- ORDER BY fallback: the table column is a STRUCT, the alias is an INT.
-- ORDER BY normally prefers the alias, but the alias (INT) cannot have
-- field 'x' extracted, so the struct column wins.
> CREATE OR REPLACE TEMPORARY VIEW s1(a) AS VALUES (named_struct('x', 1)), (named_struct('x', 2));

> SELECT -a.x AS a FROM s1 ORDER BY a.x LIMIT 1;
  -1

-- HAVING fallback: the table column is an INT, the alias is a STRUCT.
-- HAVING normally prefers the table column, but the column (INT) cannot have
-- field 'x' extracted, so the alias wins.
> CREATE OR REPLACE TEMPORARY VIEW s2(a) AS VALUES (1), (2);

> SELECT named_struct('x', 2) AS a FROM s2 GROUP BY a HAVING a.x > 1;
  {"x":2}
  {"x":2}

-- Map key extraction follows the same rules.
-- ORDER BY fallback: alias (INT) cannot have key extracted, map column wins.
> CREATE OR REPLACE TEMPORARY VIEW s3(a) AS VALUES (map('key', 100)), (map('key', 200));

> SELECT -a['key'] AS a FROM s3 ORDER BY a['key'] LIMIT 1;
  -100

-- HAVING fallback: column (INT) cannot have key extracted, map alias wins.
> CREATE OR REPLACE TEMPORARY VIEW s4(a) AS VALUES (100), (200);

> SELECT map('key', 200) AS a FROM s4 GROUP BY a HAVING a['key'] > 100;
  {"key":200}
  {"key":200}

Limitaciones

Para evitar la ejecución de consultas que puedan consumir muchos recursos, Azure Databricks limita la correlación a un nivel. Esta restricción se aplica también a las referencias de parámetros en las funciones SQL.

Ejemplos

-- Differentiating columns and fields
> SELECT a FROM VALUES(1) AS t(a);
 1

> SELECT t.a FROM VALUES(1) AS t(a);
 1

> SELECT t.a FROM VALUES(named_struct('a', 1)) AS t(t);
 1

-- A column takes precedence over a field
> SELECT t.a FROM VALUES(named_struct('a', 1), 2) AS t(t, a);
 2

-- Implict lateral column alias
> SELECT c1 AS a, a + c1 FROM VALUES(2) AS T(c1);
 2  4

-- A local column reference takes precedence, over a lateral column alias
> SELECT c1 AS a, a + c1 FROM VALUES(2, 3) AS T(c1, a);
 2  5

-- A scalar subquery correlation to S.c3
> SELECT (SELECT c1 FROM VALUES(1, 2) AS t(c1, c2)
           WHERE t.c2 * 2 = c3)
    FROM VALUES(4) AS s(c3);
 1

-- A local reference takes precedence over correlation
> SELECT (SELECT c1 FROM VALUES(1, 2, 2) AS t(c1, c2, c3)
           WHERE t.c2 * 2 = c3)
    FROM VALUES(4) AS s(c3);
  NULL

-- An explicit scalar subquery correlation to s.c3
> SELECT (SELECT c1 FROM VALUES(1, 2, 2) AS t(c1, c2, c3)
           WHERE t.c2 * 2 = s.c3)
    FROM VALUES(4) AS s(c3);
 1

-- Correlation from an EXISTS predicate to t.c2
> SELECT c1 FROM VALUES(1, 2) AS T(c1, c2)
    WHERE EXISTS(SELECT 1 FROM VALUES(2) AS S(c2)
                  WHERE S.c2 = T.c2);
 1

-- Attempt a lateral correlation to t.c2
> SELECT c1, c2, c3
    FROM VALUES(1, 2) AS t(c1, c2),
         (SELECT c3 FROM VALUES(3, 4) AS s(c3, c4)
           WHERE c4 = c2 * 2);
 [UNRESOLVED_COLUMN] `c2`

-- Successsful usage of lateral correlation with keyword LATERAL
> SELECT c1, c2, c3
    FROM VALUES(1, 2) AS t(c1, c2),
         LATERAL(SELECT c3 FROM VALUES(3, 4) AS s(c3, c4)
                  WHERE c4 = c2 * 2);
 1  2  3

-- Referencing a parameter of a SQL function
> CREATE OR REPLACE TEMPORARY FUNCTION func(a INT) RETURNS INT
    RETURN (SELECT c1 FROM VALUES(1) AS T(c1) WHERE c1 = a);
> SELECT func(1), func(2);
 1  NULL

-- A column takes precedence over a parameter
> CREATE OR REPLACE TEMPORARY FUNCTION func(a INT) RETURNS INT
    RETURN (SELECT a FROM VALUES(1) AS T(a) WHERE t.a = a);
> SELECT func(1), func(2);
 1  1

-- Qualify the parameter with the function name
> CREATE OR REPLACE TEMPORARY FUNCTION func(a INT) RETURNS INT
    RETURN (SELECT a FROM VALUES(1) AS T(a) WHERE t.a = func.a);
> SELECT func(1), func(2);
 1  NULL

-- Lateral alias takes precedence over correlated reference
> SELECT (SELECT c2 FROM (SELECT 1 AS c1, c1 AS c2) WHERE c2 > 5)
    FROM VALUES(6) AS t(c1)
  NULL

-- Lateral alias takes precedence over function parameters
> CREATE OR REPLACE TEMPORARY FUNCTION func(x INT)
    RETURNS TABLE (a INT, b INT, c DOUBLE)
    RETURN SELECT x + 1 AS x, x
> SELECT * FROM func(1)
  2 2

-- All together now
> CREATE OR REPLACE TEMPORARY VIEW lat(a, b) AS VALUES('lat.a', 'lat.b');

> CREATE OR REPLACE TEMPORARY VIEW frm(a) AS VALUES('frm.a');

> CREATE OR REPLACE TEMPORARY FUNCTION func(a INT, b int, c int)
  RETURNS TABLE
  RETURN SELECT t.*
    FROM lat,
         LATERAL(SELECT a, b, c
                   FROM frm) AS t;

> VALUES func('func.a', 'func.b', 'func.c');
  a      b      c
  -----  -----  ------
  frm.a  lat.b  func.c

Resolución de tablas y vistas

Un identificador en una referencia de tabla puede ser cualquiera de los siguientes elementos:

  • Tabla o vista persistente en Unity Catalog o el metastore de Hive
  • Expresión de tabla común (CTE)
  • Vista temporal o tabla temporal

La resolución de un identificador depende de si está completo (calificado) o no:

  • Apto

    Si el identificador está completo con tres partes (catalog.schema.relation), es único.

    Si el identificador consta de dos partes (schema.relation) se completa con el resultado de SELECT current_catalog() para que sea único.

  • Incompleto

    1. Expresión de tabla común

      Si la referencia está dentro del ámbito de una cláusula WITH, busca una coincidencia del identificador con un CTE que empiece con la cláusula contenedora WITH inmediata y se desplaza hacia fuera desde ahí.

    2. Vista temporal o tabla temporal

      Coincide con el identificador de cualquier vista temporal o tabla temporal definida dentro de la sesión actual.

    3. Tabla persistente

      Completa el identificador anteponiendo el resultado de SELECT current_catalog() y SELECT current_schema(), y lo busca como una relación persistente.

Si la relación no se puede resolver como una tabla, vista o CTE, Databricks genera el error TABLE_OR_VIEW_NOT_FOUND.

Ejemplos

-- Setting up a scenario
> USE CATALOG spark_catalog;
> USE SCHEMA default;

> CREATE TABLE rel(c1 int);
> INSERT INTO rel VALUES(1);

-- An fully qualified reference to rel:
> SELECT c1 FROM spark_catalog.default.rel;
 1

-- A partially qualified reference to rel:
> SELECT c1 FROM default.rel;
 1

-- An unqualified reference to rel:
> SELECT c1 FROM rel;
 1

-- Add a temporary view with a conflicting name:
> CREATE TEMPORARY VIEW rel(c1) AS VALUES(2);

-- For unqualified references the temporary view takes precedence over the persisted table:
> SELECT c1 FROM rel;
 2

-- Temporary views cannot be qualified, so qualifiecation resolved to the table:
> SELECT c1 FROM default.rel;
 1

-- An unqualified reference to a common table expression wins even over a temporary view:
> WITH rel(c1) AS (VALUES(3))
    SELECT * FROM rel;
 3

-- If CTEs are nested, the match nearest to the table reference takes precedence.
> WITH rel(c1) AS (VALUES(3))
    (WITH rel(c1) AS (VALUES(4))
      SELECT * FROM rel);
  4

-- To resolve the table instead of the CTE, qualify it:
> WITH rel(c1) AS (VALUES(3))
    (WITH rel(c1) AS (VALUES(4))
      SELECT * FROM default.rel);
  1

-- For a CTE to be visible it must contain the query
> SELECT * FROM (WITH cte(c1) AS (VALUES(1))
                   SELECT 1),
                cte;
  [TABLE_OR_VIEW_NOT_FOUND] The table or view `cte` cannot be found.

Resolución de funciones

Una referencia de función se reconoce por el conjunto de paréntesis finales obligatorios.

Se puede resolver como:

La resolución del nombre de una función depende de si está completo (calificado) o no:

  • Apto

    Si el nombre está completo con tres partes (catalog.schema.function), es único.

    Si el nombre consta de dos partes (schema.function), se completa con el resultado de SELECT current_catalog() para que sea único.

    A continuación, se busca la función en el catálogo.

  • Incompleto

    En el caso de los nombres de función incompletos, Azure Databricks sigue un orden de prioridad fijo (PATH):

    1. Función integrada

      Si existe una función con este nombre en el conjunto de funciones integradas, se elige esa función.

    2. Función temporal

      Si existe una función con este nombre en el conjunto de funciones temporales, se elige esa función.

    3. Función persistente

      Completa el nombre de la función anteponiendo el resultado de SELECT current_catalog() y SELECT current_schema(), y lo busca como una función persistente.

Si la función no se puede resolver, Azure Databricks genera el error UNRESOLVED_ROUTINE.

Ejemplos

> USE CATALOG spark_catalog;
> USE SCHEMA default;

-- Create a function with the same name as a builtin
> CREATE FUNCTION concat(a STRING, b STRING) RETURNS STRING
    RETURN b || a;

-- unqualified reference resolves to the builtin CONCAT
> SELECT concat('hello', 'world');
 helloworld

-- Qualified reference resolves to the persistent function
> SELECT default.concat('hello', 'world');
 worldhello

-- Create a persistent function
> CREATE FUNCTION func(a INT, b INT) RETURNS INT
    RETURN a + b;

-- The persistent function is resolved without qualifying it
> SELECT func(4, 2);
 6

-- Create a conflicting temporary function
> CREATE FUNCTION func(a INT, b INT) RETURNS INT
    RETURN a / b;

-- The temporary function takes precedent
> SELECT func(4, 2);
 2

-- To resolve the persistent function it now needs qualification
> SELECT spark_catalog.default.func(4, 3);
 6