Resolução de nomes

Aplica-se a:marca de seleção positiva SQL do Databricks marca de seleção positiva Azure Databricks Runtime

Resolução de nomes é o processo pelo qual identificadores são resolvidos para referências de coluna, campo, parâmetro ou tabela específicas.

Resolução da variável, coluna, campo e parâmetro

Identificadores em expressões podem ser referências a qualquer um dos seguintes itens:

A resolução de nomes aplica os seguintes princípios:

  • A referência correspondente mais próxima vence; e
  • As colunas e o parâmetro vencem sobre campos e chaves.

Em detalhes, a resolução de identificadores para uma referência específica segue estas regras na ordem:

  1. Referências de local

    1. Referência de coluna

      Corresponde o identificador, que pode ser qualificado, a um nome de coluna em uma referência de tabela da FROM clause.

      Se houver mais de uma correspondência desse tipo, gera um erro AMBIGUOUS_COLUMN_OR_FIELD.

    2. Referência de função sem parâmetros

      Se o identificador não for qualificado e corresponder a current_user, current_date ou current_timestamp: resolva-o como uma dessas funções.

    3. Especificação de coluna DEFAULT

      Se o identificador não for qualificado, corresponder a default e criar a expressão inteira no contexto de um UPDATE SET, INSERT VALUES ou MERGE WHEN [NOT] MATCHED: resolva como o respectivo valor DEFAULT da tabela de destino de INSERT, UPDATE ou MERGE.

    4. Referência de chave de mapa ou campo struct

      Se o identificador for qualificado, tente combiná-lo com um campo ou uma chave de mapa de acordo com as seguintes etapas:

      a. Remova o último identificador e trate-o como um campo ou chave. B. Corresponda o restante a uma coluna na referência de tabela da FROM clause.

      Se houver mais de uma correspondência desse tipo, gera um erro AMBIGUOUS_COLUMN_OR_FIELD.

      Se houver uma correspondência e a coluna for:

      • STRUCT: corresponda ao campo.

        Se o campo não puder ser correspondido, gera um erro de FIELD_NOT_FOUND.

        Se houver mais de um campo, gera um erro AMBIGUOUS_COLUMN_OR_FIELD.

      • MAP: gera um erro se a chave for qualificada.

        Um erro de runtime poderá ocorrer se a chave não estiver realmente presente no mapa.

      • Qualquer outro tipo: gera um erro. C. Repita a etapa anterior para remover o identificador à direita como um campo. Aplique as regras (A) e (B) enquanto houver um identificador à esquerda para interpretar como uma coluna.

  2. Alias de coluna lateral

    Aplica-se a:verificação marcada como sim SQL do Databricks verificação marcada como sim Databricks Runtime 12.2 LTS e versões posteriores

    Se a expressão estiver dentro de uma lista SELECT, corresponde o identificador principal a um alias de coluna anterior nessa lista SELECT.

    Se houver mais de uma correspondência desse tipo, gera um erro AMBIGUOUS_LATERAL_COLUMN_ALIAS.

    Corresponde cada identificador restante como um campo ou uma chave de mapa e gera o erro FIELD_NOT_FOUND ou AMBIGUOUS_COLUMN_OR_FIELD se eles não puderem ser correspondidos.

  3. Correlação

    • LATERAL

      Se a consulta for precedida por uma palavra-chave LATERAL, aplique as regras 1.a e 1.d considerando as referências de tabela no FROM que contém a consulta e precedendo a LATERAL.

    • Regular

      Se a consulta for uma subconsulta escalar, IN ou EXISTS subconsulta, aplique as regras 1.a, 1.d e 2 considerando as referências de tabela na cláusula da FROM consulta que contém.

  4. Correlação aninhada

    Aplica-se a:com marca de verificação sim Databricks SQL marcado com marca sim Databricks Runtime 20.0 e superiores

    Reaplique a regra 3, iterando sobre os níveis de aninhamento da consulta, para que um identificador possa resolver para uma referência correlacionada em qualquer consulta envolvente, não apenas na que encerra imediatamente.

  5. Loop FOR

    Se a instrução estiver contida em um FOR loop:

    a. Corresponda o identificador a uma coluna em uma instrução de loop FOR. Se o identificador for qualificado, o qualificador deverá corresponder ao nome da variável de loop FOR, se definido. B. Se o identificador for qualificado, corresponda a um campo ou chave de mapa de um parâmetro seguindo a regra 1.c

  6. Instrução composta

    Se a instrução estiver contida em uma instrução composta:

    a. Corresponda o identificador a uma variável declarada nessa instrução composta. Se o identificador for qualificado, o qualificador deverá corresponder ao rótulo da instrução composta se um tiver sido definido. B. Se o identificador for qualificado, corresponda a um campo ou chave de mapeamento de uma variável seguindo a regra 1.c

  7. Instrução composta aninhada ou FOR loop

    Reaplique as regras 5 e 6, iterando sobre os níveis hierárquicos de aninhamento da instrução composta.

  8. Parâmetros de rotina

    Se a expressão fizer parte de uma instrução CREATE FUNCTIONCREATE PROCEDURE:

    1. Corresponda o identificador a um nome de parâmetro. Se o identificador for qualificado, o qualificador deverá corresponder ao nome da rotina.
    2. Se o identificador for qualificado, corresponda a um campo ou chave de mapa de um parâmetro seguindo a regra 1.c
  9. Variáveis de sessão

    1. Corresponder o identificador a um nome de variável. Se o identificador for qualificado, o qualificador deverá ser session ou system.session.
    2. Se o identificador for qualificado, corresponda a um campo ou chave de mapeamento de uma variável seguindo a regra 1.c

Resolução de nomes em HAVING, ORDER BYe QUALIFY

As HAVINGcláusulas , ORDER BYe QUALIFY podem referenciar nomes da SELECT lista, bem como colunas das tabelas subjacentes. Quando um nome em uma dessas cláusulas corresponde a um alias de coluna na SELECT lista e a uma coluna de tabela, as cláusulas resolvem a ambiguidade de forma diferente:

  • ORDER BYprefere o alias deSELECT lista em vez da coluna da tabela.
  • HAVING prefere a coluna da tabela em vez do alias de SELECT lista.
  • QUALIFY prefere a coluna da tabela em vez do alias de SELECT lista (o mesmo que HAVING).

Exemplos

> 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

Extração de campo e prioridade de resolução de nomes

Quando um nome qualificado, como a.b é usado ou HAVINGORDER BY, as regras de prioridade acima ainda se aplicam, mas com uma consideração adicional: o candidato preferencial deve dar suporte ao campo struct ou à extração de chave de mapa. Se isso não acontecer, o outro candidato será usado em vez disso.

Por exemplo, se o alias a for resolvido para uma simples, INT mas a coluna a de tabela for um STRUCT campo xcom, ORDER BY escolha a STRUCT coluna porque um campo não pode ser extraído do alias INT . Por outro lado, se a coluna da tabela for simples INT e o alias for um STRUCT, HAVING retornará ao alias para extração de campo.

Exemplos

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

Limitações

No Databricks SQL e Databricks Runtime 20.0 e superiores, correlação aninhada (uma subconsulta que faz referência a colunas de uma consulta anexa além de seu pai imediato) é suportada, com as seguintes limitações:

  • Correlação aninhada não é suportada para subconsultas em uma HAVING cláusula.
  • Uma LATERAL subconsulta não pode ser aninhada-correlacionada. Suas referências externas devem se resolver para a consulta que envolve diretamente.

Nas versões de tempo de execução do Databricks abaixo da 20.0, a correlação é limitada a um único nível: uma subconsulta só pode referenciar colunas da consulta que imediatamente a envolve.

Exemplos

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

-- Nested correlation: the innermost EXISTS references t1.a from the outermost query
> CREATE OR REPLACE TEMPORARY VIEW t1(a) AS VALUES(1), (2), (3);
> CREATE OR REPLACE TEMPORARY VIEW t2(b) AS VALUES(1), (2);
> CREATE OR REPLACE TEMPORARY VIEW t3(c) AS VALUES(2), (3);

> SELECT a FROM t1
    WHERE EXISTS(SELECT 1 FROM t2
                  WHERE t2.b = t1.a
                    AND EXISTS(SELECT 1 FROM t3
                                WHERE t3.c = t1.a));
 2

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

Resolução de tabela e exibição

Um identificador em table-reference pode ser qualquer um dos seguintes:

  • Tabela ou exibição persistente no Catálogo Unity ou no Metastore do Hive
  • CTE (expressão de tabela comum)
  • Exibição temporária ou tabela temporária

A resolução de um identificador depende se ele é qualificado:

  • Qualificado

    Se o identificador for totalmente qualificado com três partes: catalog.schema.relation, ele será exclusivo.

    Se o identificador consistir em duas partes: schema.relation, ele será qualificado adicionalmente com o resultado de SELECT current_catalog() para torná-lo exclusivo.

  • Não qualificado

    1. Expressão de tabela comum

      Se a referência estiver dentro do escopo de uma cláusula WITH, corresponda o identificador a uma CTE começando com a cláusula WITH imediatamente contida e movendo para fora dela.

    2. Exibição temporária ou tabela temporária

      Corresponda o identificador a qualquer exibição temporária ou tabela temporária definida dentro da sessão atual.

    3. Tabela persistida

      Qualifique totalmente o identificador pré-pendente do resultado de SELECT current_catalog() e SELECT current_schema() e procure-o como uma relação persistente.

Se a relação não puder ser resolvida para nenhuma tabela, exibição ou CTE, o Databricks gerará um erro de TABLE_OR_VIEW_NOT_FOUND.

Exemplos

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

Resolução de função

Uma referência de função é reconhecida pelo conjunto de parênteses à direita obrigatório.

Ela pode resolver para:

A resolução de um nome de função depende se ele é qualificado:

  • Qualificado

    Se o nome for totalmente qualificado com três partes: catalog.schema.function, ele será exclusivo.

    Se o nome consistir em duas partes: schema.function, ele será qualificado adicionalmente com o resultado de SELECT current_catalog() para torná-lo exclusivo.

    Em seguida, a função é pesquisada no catálogo.

  • Não qualificado

    Para nomes de função não qualificados, o Azure Databricks segue uma ordem fixa de precedência (PATH):

    1. Função interna

      Se existir uma função com esse nome entre o conjunto de funções internas, essa função será escolhida.

    2. Função temporária

      Se existir uma função com esse nome entre o conjunto de funções temporárias, essa função será escolhida.

    3. Função persistida

      Qualifique totalmente a função pré-pendente do resultado de SELECT current_catalog() e SELECT current_schema() e procure-a como uma função persistente.

Se a função não puder ser resolvida, o Azure Databricks gerará um erro UNRESOLVED_ROUTINE.

Exemplos

> 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