名稱解析
適用於:Databricks SQL Databricks Runtime
名稱解析是將 標識符 解析為特定的 column、欄位、參數或 table參照的過程。
Column、欄位、參數和變數解析
運算式中的識別碼可以是下列任一項的參考:
- 根據檢視、table、通用 table 表示式 (CTE) 或 column_alias,Column 名稱。
- 結構或對應內的功能變數名稱或對應索引鍵。 欄位和索引鍵永遠無法限定。
- SQL 使用者定義函數的參數名稱。
- 變數名稱。
- 特殊函式,例如
current_user
或current_date
,不需要 使用()
。 -
DEFAULT
關鍵詞,用於INSERT
、UPDATE
、MERGE
或SET VARIABLE
的內容中,將 column 或變數值 set 為其預設值。
名稱解析會套用下列原則:
- 最接近的比對參考會獲勝,且
- Columns 和參數優先於欄位和鍵值。
詳細來說,將標識碼解析為特定參考會遵循下列規則:
本機參考
Column 參考
在
FROM clause
table 的 參考中,將可能限定的 identifier比對到 column 名稱。如果有一個以上的相符專案,請引發 AMBIGUOUS_COLUMN_OR_FIELD 錯誤。
無參數函式參考
如果 identifier 不合格,且符合
current_user
、current_date
或current_timestamp
:將其解析為下列其中一個函式。Column DEFAULT(規格)
如果 identifier 不合格,則會比對
default
,並在UPDATE SET
、INSERT VALUES
或MERGE WHEN [NOT] MATCHED
的上下文中構成整個表達式:將其解析為INSERT
、UPDATE
或MERGE
之目標 table 的相應DEFAULT
值。結構欄位或對應索引鍵參考
如果 identifier 符合條件,請按照下列步驟,嘗試將其比對到欄位或映射鍵:
A. Remove 最後一個 identifier,並將它視為字段或索引鍵。 B. 比對 table 參考
FROM clause
中的餘數與 column。如果有一個以上的相符專案,請引發 AMBIGUOUS_COLUMN_OR_FIELD 錯誤。
如果有相符項目,且 column 是:
STRUCT
:比對欄位。如果無法比對欄位,請引發 FIELD_NOT_FOUND 錯誤。
如果有多個字段,請引發 AMBIGUOUS_COLUMN_OR_FIELD 錯誤。
MAP
:如果索引鍵為限定,則引發錯誤。如果索引鍵實際上不存在於對應中,可能會發生運行時間錯誤。
任何其他類型:引發錯誤。 C. 重複上述步驟,將 identifier 的尾端 remove 設為欄位。 套用規則 (A) 和 (B) ,而左側有 identifier,以解譯為 column。
橫向 column 別名
適用於: Databricks SQL Databricks Runtime 12.2 LTS 和更新版本
如果表達式位於
SELECT
list內,請將前置 identifier 與該SELECT
list中的前置 column 別名 相符。如果有一個以上的相符專案,請引發 AMBIGUOUS_LATERAL_COLUMN_ALIAS 錯誤。
比對每個剩餘的 identifier 作為字段或地圖索引鍵,並在無法比對時引發 FIELD_NOT_FOUND 或 AMBIGUOUS_COLUMN_OR_FIELD 錯誤。
相互關聯
側面的
如果查詢前面加上
LATERAL
關鍵詞,請套用規則 1.a 和 1.d,考慮包含查詢的FROM
中 table 參考,並在LATERAL
之前。一般
如果查詢是 純量子查詢、子查詢、
IN
子查詢或EXISTS
子查詢,則套用規則 1.a、1.d 和 2,並考慮包含查詢的FROM
子句中的 table 參考。
巢狀相互關聯
重新套用規則 3 逐一查看查詢的巢狀層級。
例程 parameters
如果表達式是 CREATE FUNCTION 語句的一部分:
- 請將 identifier 匹配到 參數名稱。 如果 identifier 符合資格,則限定符必須與函式的名稱相匹配。
- 如果 identifier 合格,依照規則 1.c,將其匹配至參數的欄位或映射鍵
變數
- 比對 identifier 與 變數名稱。 如果 identifier 是合格的,那麼限定符必須是
session
或system.session
。 - 如果 identifier 被認定合格,則根據規則 1.c 將它匹配至變數的欄位或映射鍵。
- 比對 identifier 與 變數名稱。 如果 identifier 是合格的,那麼限定符必須是
限制
為了避免執行可能昂貴的相互關聯查詢,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
Table 和檢視解析度
table-reference 中的 identifier 可以是下列任一項:
- 持續性 table 或在 Unity 中的檢視 Catalog 或 Hive 中繼資料存放區
- 常用 table 表達式 (CTE)
- 暫存檢視
identifier 的解決取決於其是否合格:
合格
如果 identifier 由三個部分完整限定為
catalog.schema.relation
,則是唯一的。如果 identifier 包含兩個部分:
schema.relation
,則會進一步限定SELECT current_catalog()
的結果,使其是唯一的。不合格的
常見 table 表示式
如果參考位於
WITH
子句的範圍內,請將 identifier 與 CTE 進行匹配,從立即包含的WITH
子句開始,然後向外進行搜尋。暫存檢視
比對 identifier 與目前會話內定義的任何暫存檢視。
持續 table
完全 qualify 和 identifier,方法是將
SELECT current_catalog()
和SELECT current_schema()
的結果加到前面,並作為持續性關聯來查找。
如果關聯無法解析為任何 table、視圖或 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.
函式解析
函式參考通過括弧後必須添加的 set 來識別。
它可以解析為:
- Azure Databricks 提供的內建函式,
- 限定為目前會話的暫時 使用者定義函式 ,或
- 儲存在 Hive 中繼存放區或 Unity Catalog中的永久性使用者定義函式。
函式名稱的解析取決於函式名稱是否合格:
合格
如果名稱具有三個部分的完整名稱:
catalog.schema.function
,則是唯一的。如果名稱包含兩個部分:
schema.function
,則會進一步限定其結果SELECT current_catalog()
,使其是唯一的。函式接著會在 catalog中查閱。
不合格的
針對未限定的函式名稱,Azure Databricks 會遵循固定優先順序 (
PATH
):內建函式
如果此名稱的函式存在於內建函式 set 中,則會選擇該函式。
暫存函式
如果此名稱的函式存在於暫存函式 set 中,則會選擇該函式。
Persisted 函式
完整 qualify 函式名稱,方法是將
SELECT current_catalog()
和SELECT current_schema()
的結果前置,並將其查找為持續性函式。
如果無法解析函式,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