名稱解析
適用於:Databricks SQL Databricks Runtime
名稱解析是將 標識符 解析為特定的欄位、欄位、參數或資料表參照的過程。
數據行、欄位、參數和變數解析
運算式中的識別碼可以是下列任一項的參考:
- 以檢視、表格、通用表格表達式 (CTE) 或 欄位別名為基礎的欄位名稱。
- 結構或對應內的功能變數名稱或對應索引鍵。 欄位和索引鍵永遠無法限定。
- SQL 使用者定義函數的參數名稱。
- 變數名稱。
- 特殊函式,例如
current_user
或current_date
,不需要 使用()
。 -
DEFAULT
關鍵詞,用於INSERT
、UPDATE
、MERGE
或SET VARIABLE
的內容中,將欄位或變數值設定為其預設值。
名稱解析會套用下列原則:
- 最接近的比對參考會獲勝,且
- 欄和參數優於欄位和鍵。
詳細來說,將標識碼解析為特定參考會遵循下列規則:
本機參考
欄位參考
比對可能限定的標識碼,與 之
FROM clause
中的數據行名稱相符。如果有一個以上的相符專案,請引發 AMBIGUOUS_COLUMN_OR_FIELD 錯誤。
無參數函式參考
如果標識符不限定且符合
current_user
、current_date
或current_timestamp
:將其解析為下列其中一個函式。欄位 DEFAULT 規格
如果標識元不合格,則會比對
default
,並在UPDATE SET
、INSERT VALUES
或MERGE WHEN [NOT] MATCHED
的內容中組成整個表達式:解析為DEFAULT
、INSERT
或UPDATE
之目標數據表的個別MERGE
值。結構欄位或對應索引鍵參考
如果標識碼是合格的,則請根據下列步驟,努力將標識碼與字段或對應索引鍵比對:
A. 拿掉最後一個識別碼,並將它視為字段或索引鍵。 B. 將餘數比對到中
FROM clause
的一欄。如果有一個以上的相符專案,請引發 AMBIGUOUS_COLUMN_OR_FIELD 錯誤。
如果有對應項目,且數據行是:
STRUCT
:比對欄位。如果無法比對欄位,請引發 FIELD_NOT_FOUND 錯誤。
如果有多個字段,請引發 AMBIGUOUS_COLUMN_OR_FIELD 錯誤。
MAP
:如果索引鍵為限定,則引發錯誤。如果索引鍵實際上不存在於對應中,可能會發生運行時間錯誤。
任何其他類型:引發錯誤。 C. 重複上述步驟,將尾端標識碼作為欄位來移除。 套用規則 (A) 和 (B) 時,還有一個識別碼可解譯為數據行。
橫向欄別名
適用於: Databricks SQL Databricks Runtime 12.2 LTS 和更新版本
如果表達式位於
SELECT
清單中,請將開頭識別符與該 清單中先前的SELECT
相符。如果有一個以上的相符專案,請引發 AMBIGUOUS_LATERAL_COLUMN_ALIAS 錯誤。
比對每個剩餘的識別碼作為欄位或映射鍵,並在無法比對時拋出 FIELD_NOT_FOUND 或 AMBIGUOUS_COLUMN_OR_FIELD 錯誤。
相互關聯
側面的
如果查詢前面加上
LATERAL
關鍵詞,請套用規則 1.a 和 1.d,並考慮在包含查詢的FROM
中的表格參考,且此參考位於LATERAL
之前。一般
如果查詢是 純量子查詢,、
IN
或EXISTS
子查詢會套用規則 1.a、1.d 和 2,並考慮包含查詢FROM
子句中的數據表參考。
巢狀相互關聯
重新套用規則 3 逐一查看查詢的巢狀層級。
例程參數
如果表達式是 CREATE FUNCTION 語句的一部分:
- 比對標識碼與 參數名稱。 如果標識元為限定符,限定符必須符合函式的名稱。
- 如果識別碼是合格的,請依照規則 1.c 匹配參數的欄位或映射鍵。
變數
- 比對識別碼與 變數名稱。 如果識別元為限定元,則限定子必須
session
或system.session
。 - 如果標識符是合格的,則根據規則 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 Catalog 或 Hive Metastore 中的持久性表格或檢視表
- 通用資料表表示式 (CTE)
- 暫存檢視
識別碼的解決取決於標識碼是否合格:
合格
如果識別碼由三個部分組成,例如:
catalog.schema.relation
,則它是唯一的。如果標識碼由兩個部分組成:
schema.relation
,則會進一步透過SELECT current_catalog()
的結果來限定,使其唯一。不合格的
公用表達式
如果參考位於
WITH
子句的範圍內,請將標識符與 CTE 比對,從最先包含該參考的WITH
子句開始,然後依次向外擴展比較。暫存檢視
將識別碼與目前會話內定義的任何暫存檢視進行比對。
持久化表
藉由預先暫止
SELECT current_catalog()
和SELECT current_schema()
的結果來完整限定標識符,並將其查閱為持續性關聯。
如果關聯無法解析為任何數據表、檢視或 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.
函式解析
函式參考是由一組必要的尾端括弧所辨識。
它可以解析為:
- Azure Databricks 提供的內建函式,
- 限定為目前會話的暫時 使用者定義函式 ,或
- 儲存在 Hive 中繼存放區或 Unity Catalog 中的永久性使用者自定義函數。
函式名稱的解析取決於函式名稱是否合格:
合格
如果名稱具有三個部分的完整名稱:
catalog.schema.function
,則是唯一的。如果名稱包含兩個部分:
schema.function
,則會進一步限定其結果SELECT current_catalog()
,使其是唯一的。函式接著會在目錄中查閱。
不合格的
針對未限定的函式名稱,Azure Databricks 會遵循固定優先順序 (
PATH
):內建函式
如果此名稱的函式存在於一組內建函式中,則會選擇該函式。
暫存函式
如果此名稱的函式存在於暫存函式集合中,則會選擇該函式。
Persisted 函式
藉由預先暫止
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