Resolução de nomes

Aplica-se a:Assinalado sim Databricks SQL Assinalado sim Databricks Runtime

A resolução de nomes é o processo pelo qual identificadores são associados a referências específicas de coluna, campo, parâmetro ou tabela.

Resolução de colunas, campos, parâmetros e variáveis

Os identificadores em expressões podem ser referências a qualquer um dos seguintes:

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

  • A referência correspondente mais próxima vence, e
  • Colunas e parâmetros superam campos e chaves.

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

  1. Referências locais

    1. Referência da coluna

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

      Se houver mais de uma correspondência, levante 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_dateou current_timestamp, resolva-o como uma destas funções.

    3. Especificação padrão da coluna

      Se o identificador não for qualificado, corresponder ao default e constituir toda a expressão no contexto de um UPDATE SET, INSERT VALUESou MERGE WHEN [NOT] MATCHED, resolve-se como o respetivo valor de DEFAULT da tabela de destino do INSERT, UPDATE ou MERGE.

    4. Referência da chave do campo struct ou do mapa

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

      Um. Remova o último identificador e trate-o como um campo ou chave. B. Corresponder o resto a uma coluna na referência de tabela de do FROM clause.

      Se houver mais de uma correspondência, levante um erro AMBIGUOUS_COLUMN_OR_FIELD.

      Se houver uma correspondência e a coluna for uma:

      • STRUCT: Corresponda ao campo.

        Se o campo não puder ser encontrado, gere um erro FIELD_NOT_FOUND.

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

      • MAP: Provocar um erro se a chave estiver qualificada.

        Pode ocorrer um erro de execução se a chave não estiver realmente presente no mapa.

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

  2. Aliasing de coluna lateral

    Aplica-se a:assinalado como sim Databricks SQL assinalado como sim Databricks Runtime 12.2 LTS e superior

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

    Se houver mais de uma dessas correspondências, levante um erro AMBIGUOUS_LATERAL_COLUMN_ALIAS.

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

  3. Correlação

    • LATERAIS

      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 precede a LATERAL.

    • Regular

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

  4. Correlação aninhada

    Aplica-se a:assinalado Databricks SQL assinalado sim Databricks Runtime 20.0 e superiores

    Reaplique-se 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 loop FOR:

    Um. Corresponda o identificador a uma coluna em uma consulta de 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, seguindo a regra 1.c, a uma chave de campo ou mapa de um parâmetro.

  6. Declaração composta

    Se a declaração estiver contida numa declaração composta:

    Um. Corresponder o identificador a uma variável declarada nessa instrução composta. Se o identificador for qualificado, o qualificador deve corresponder ao rótulo da instrução composta caso este tenha sido definido. B. Se o identificador for qualificado, corresponda a um campo ou chave de mapa de uma variável seguindo a regra 1.c

  7. Instrução composta aninhada ou loop FOR

    Reaplique as regras 5 e 6, percorrendo os níveis de aninhamento da declaração composta.

  8. Parâmetros de rotina

    Se a expressão fizer parte de uma instrução CREATE FUNCTION ou CREATE 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, seguindo a regra 1.c, a uma chave de campo ou mapa de um parâmetro.
  9. variáveis de sessão

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

Resolução de nomes em HAVING, ORDER BY, e QUALIFY

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

  • ORDER BY prefere o SELECT alias de lista à coluna da tabela.
  • HAVING prefere a coluna da tabela ao SELECT alias da lista.
  • QUALIFY prefere a coluna da tabela ao SELECT alias da lista (igual a 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 campos e prioridade de resolução de nomes

Quando um nome qualificado, como a.b o que é usado em HAVING ou ORDER BY, as regras de prioridade acima ainda se aplicam, mas com uma consideração adicional: o candidato preferido deve suportar a extração de campos de estruturas ou de chaves de mapa. Se não o fizer, é usado o outro candidato em seu lugar.

Por exemplo, se o alias a se resolve para um plano INT mas a coluna a da tabela for um STRUCT campo xcom , ORDER BY escolhe a STRUCT coluna porque um campo não pode ser extraído do INT alias. Por outro lado, se a coluna da tabela for um plano INT e o alias for um STRUCT, HAVING recorre ao alias para extração de campos.

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, é suportada correlação aninhada (uma subconsulta que faz referência a colunas de uma consulta anexa para além do seu pai imediato), com as seguintes limitações:

  • A correlação aninhada não é suportada para subconsultas numa HAVING cláusula.
  • Uma LATERAL subconsulta não pode ser aninhada-correlacionada. As suas referências externas devem ser resolvidas para a consulta diretamente anexa.

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

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 tabelas e visualizações

Um identificador na referência de tabela pode ser qualquer um dos seguintes:

  • Tabela ou exibição persistente no Unity Catalog ou no Hive Metastore
  • Expressão de tabela comum (CTE)
  • Vista temporária ou tabela temporária

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

  • Qualificado

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

    Se o identificador consistir em duas partes: schema.relation, ele é ainda mais qualificado com o resultado de SELECT current_catalog() para torná-lo único.

  • Não qualificado

    1. Expressão de tabela comum

      Se a referência estiver dentro do escopo de uma cláusula WITH, associe o identificador a um CTE, começando pela cláusula que contém imediatamente WITH e movendo-se para fora a partir daí.

    2. Vista temporária ou tabela temporária

      Associe o identificador a qualquer vista temporária ou tabela temporária definida na sessão atual.

    3. Tabela persistente

      Qualifique totalmente o identificador antecipando o 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 qualquer tabela, exibição ou CTE, o Databricks gerará um erro 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ções

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

Pode resolver em:

  • Uma função incorporada fornecida pelo Azure Databricks,
  • Uma função temporária definida pelo usuário com escopo para a sessão atual, ou
  • Uma função definida pelo utilizador persistente armazenada no Hive Metastore ou no Catálogo Unity.

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, é considerado único.

    Se o nome consiste em duas partes: schema.function, ele é ainda mais especificado com o resultado de SELECT current_catalog() para torná-lo único.

    A função é entã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 embutida

      Se existir uma função com este nome entre o conjunto de funções incorporadas, essa função é escolhida.

    2. Função temporária

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

    3. Função persistente

      Qualifique totalmente o nome da função antecipando o resultado de SELECT current_catalog() e SELECT current_schema() e procure-o como uma função persistente.

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

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