名稱解析

適用於:檢查標示為是 Databricks SQL 檢查標示為是 Databricks Runtime

名稱解析是標識碼解析為特定數據行、field-、parameter-或 table-references 的程式

數據行、欄位、參數和變數解析

運算式中的識別碼可以是下列任一項的參考:

名稱解析會套用下列原則:

  • 最接近比對參考會獲勝,且
  • 數據行和參數會戰勝欄位和索引鍵。

詳細來說,將標識碼解析為特定參考會遵循下列規則:

  1. 本機參考

    1. 數據行參考

      比對可能限定的標識碼,與數據表參考FROM clause中的數據行名稱相符。

      如果有一個以上的相符專案,請引發 AMBIGUOUS_COLUMN_OR_FIELD 錯誤。

    2. 無參數函式參考

      如果標識元不合格且符合 current_usercurrent_datecurrent_timestamp:將其解析為下列其中一個函式。

    3. 數據行 DEFAULT 規格

      如果標識元不合格,則會比default對 ,並在、 INSERT VALUESMERGE WHEN [NOT] MATCHED的內容中UPDATE SET組成整個運算式:解析為、 或 MERGE的目標數據表INSERTUPDATE的個別DEFAULT值。

    4. 結構欄位或對應索引鍵參考

      如果標識碼是合格的,則請根據下列步驟,努力將標識碼與字段或對應索引鍵比對:

      A. 拿掉最後一個識別碼,並將它視為字段或索引鍵。 B. 比對的其餘部分與數據表參考FROM clause中的數據行。

      如果有一個以上的相符專案,請引發 AMBIGUOUS_COLUMN_OR_FIELD 錯誤。

      如果有相符專案,且數據行為:

      • STRUCT:比對欄位。

        如果無法比對欄位,請引發 FIELD_NOT_FOUND 錯誤。

        如果有多個字段,請引發 AMBIGUOUS_COLUMN_OR_FIELD 錯誤。

      • MAP:如果索引鍵為限定,則引發錯誤。

        如果索引鍵實際上不存在於對應中,可能會發生運行時間錯誤。

      • 任何其他類型:引發錯誤。 C. 重複上述步驟,將尾端標識碼移除為欄位。 套用規則 (A) 和 (B) 時,還有一個識別碼可解譯為數據行。

  2. 橫向數據行別名

    適用於:檢查標示為是 Databricks SQL 檢查標示為是 Databricks Runtime 12.2 LTS 和更新版本

    如果表達式位於SELECT清單中,請將前置標識碼與該SELECT清單中的前一個數據行別名相符。

    如果有一個以上的相符專案,請引發 AMBIGUOUS_LATERAL_COLUMN_ALIAS 錯誤。

    比對每個剩餘的標識碼作為字段或地圖索引鍵,並在無法比對時引發 FIELD_NOT_FOUNDAMBIGUOUS_COLUMN_OR_FIELD 錯誤。

  3. 相互關聯

    • 如果查詢前面加上 LATERAL 關鍵字,請套用規則 1.a 和 1.d,考慮包含查詢的 中的 FROM 資料表參考,並在 前面 LATERAL加上 。

    • 一般

      如果查詢是純量子查詢,INEXISTS子查詢會套用規則 1.a、1.d 和 2,並考慮包含查詢子FROM句中的數據表參考。

  4. 巢狀相互關聯

    重新套用規則 3 逐一查看查詢的巢狀層級。

  5. 例程參數

    如果表示式是 CREATE FUNCTION 語句的一部分:

    1. 比對標識碼與 參數名稱。 如果標識元為限定符,限定符必須符合函式的名稱。
    2. 如果標識碼是限定的,請符合規則 1.c 之後參數的欄位或對應索引鍵
  6. 變數

    1. 比對標識碼與 變數名稱。 如果識別元為限定元,限定符必須是 sessionsystem.session
    2. 如果標識元限定,請符合規則 1.c 之後變數的欄位或對應索引鍵

限制

為了避免執行可能昂貴的相互關聯查詢,Azure Databricks 會將支援的相互關聯限制為一個層級。 這項限制也適用於 SQL 函式中的參數參考。

範例

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

數據表和檢視解析

資料表參考中的識別碼可以是下列任一項:

  • Unity 目錄或Hive中繼存放區中的永續性數據表或檢視
  • 通用資料表表示式 (CTE)
  • 暫存檢視

識別碼的解決取決於標識碼是否合格:

  • 合格

    如果標識碼具有三個部分的完整標識碼: catalog.schema.relation,則是唯一的。

    如果標識碼是由兩個部分所組成: schema.relation,則會進一步限定其結果 SELECT current_catalog() ,使其是唯一的。

  • 合格

    1. 通用數據表表達式

      如果參考位於 子句的範圍內 WITH ,請比對標識符與 CTE,從立即包含 WITH 子句開始,然後從該處向外移動。

    2. 暫存檢視

      比對標識碼與目前會話內定義的任何暫存檢視。

    3. 保存的數據表

      藉由預先擱置和 SELECT current_schema() 的結果SELECT current_catalog()來完整限定標識碼,並將其查閱為持續性關聯。

如果關聯無法解析為任何數據表、檢視或 CTE,Databricks 就會 引發TABLE_OR_VIEW_NOT_FOUND 錯誤。

範例

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

函式解析

函式參考是由一組必要的尾端括弧所辨識。

它可以解析為:

函式名稱的解析取決於函式名稱是否合格:

  • 合格

    如果名稱具有三個部分的完整名稱: catalog.schema.function,則是唯一的。

    如果名稱包含兩個部分: schema.function,則會進一步限定其結果 SELECT current_catalog() ,使其是唯一的。

    函式接著會在目錄中查閱。

  • 合格

    針對未限定的函式名稱,Azure Databricks 會遵循固定優先順序 (PATH):

    1. 內建函式

      如果此名稱的函式存在於一組內建函式中,則會選擇該函式。

    2. 暫存函式

      如果此名稱的函式存在於暫存函式集合中,則會選擇該函式。

    3. Persisted 函式

      藉由預先擱置和SELECT current_schema()的結果SELECT current_catalog()來完整限定函式名稱,並將其查閱為永續性函式。

如果無法解析函式,Azure Databricks 就會 UNRESOLVED_ROUTINE 引發錯誤。

範例

> 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