名稱解析
適用於: Databricks SQL Databricks Runtime
名稱解析是標識碼解析為特定數據行、field-、parameter-或 table-references 的程式。
數據行、欄位、參數和變數解析
運算式中的識別碼可以是下列任一項的參考:
- 以檢視、數據表、通用數據表表達式 (CTE) 或column_alias為基礎的數據行名稱。
- 結構或對應內的功能變數名稱或對應索引鍵。 欄位和索引鍵永遠無法限定。
- SQL 使用者定義函數的參數名稱。
- 變數名稱。
- 特殊函式,例如
current_user
或current_date
,不需要 使用()
。 - 、
DEFAULT
、MERGE
或SET VARIABLE
內容中用來將資料行或變數值設定為其預設值的INSERT
UPDATE
關鍵詞。
名稱解析會套用下列原則:
- 最接近的比對參考會獲勝,且
- 數據行和參數會戰勝欄位和索引鍵。
詳細來說,將標識碼解析為特定參考會遵循下列規則:
本機參考
數據行參考
比對可能限定的標識碼,與數據表參考
FROM clause
中的數據行名稱相符。如果有一個以上的相符專案,請引發 AMBIGUOUS_COLUMN_OR_FIELD 錯誤。
無參數函式參考
如果標識元不合格且符合
current_user
、current_date
或current_timestamp
:將其解析為下列其中一個函式。數據行 DEFAULT 規格
如果標識元不合格,則會比
default
對 ,並在、INSERT VALUES
或MERGE WHEN [NOT] MATCHED
的內容中UPDATE SET
組成整個運算式:解析為、 或MERGE
的目標數據表INSERT
UPDATE
的個別DEFAULT
值。結構欄位或對應索引鍵參考
如果標識碼是合格的,則請根據下列步驟,努力將標識碼與字段或對應索引鍵比對:
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 目錄或Hive中繼存放區中的永續性數據表或檢視
- 通用資料表表示式 (CTE)
- 暫存檢視
識別碼的解決取決於標識碼是否合格:
合格
如果標識碼具有三個部分的完整標識碼:
catalog.schema.relation
,則是唯一的。如果標識碼是由兩個部分所組成:
schema.relation
,則會進一步限定其結果SELECT current_catalog()
,使其是唯一的。不合格的
通用數據表表達式
如果參考位於 子句的範圍內
WITH
,請比對標識符與 CTE,從立即包含WITH
子句開始,然後從該處向外移動。暫存檢視
比對標識碼與目前會話內定義的任何暫存檢視。
保存的數據表
藉由預先擱置和
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.
函式解析
函式參考是由一組必要的尾端括弧所辨識。
它可以解析為:
- Azure Databricks 提供的內建函式,
- 限定為目前會話的暫時 使用者定義函式 ,或
- 儲存在Hive中繼存放區或 Unity 目錄中的持續性使用者定義函數。
函式名稱的解析取決於函式名稱是否合格:
合格
如果名稱具有三個部分的完整名稱:
catalog.schema.function
,則是唯一的。如果名稱包含兩個部分:
schema.function
,則會進一步限定其結果SELECT current_catalog()
,使其是唯一的。函式接著會在目錄中查閱。
不合格的
針對未限定的函式名稱,Azure Databricks 會遵循固定優先順序 (
PATH
):內建函式
如果此名稱的函式存在於一組內建函式中,則會選擇該函式。
暫存函式
如果此名稱的函式存在於暫存函式集合中,則會選擇該函式。
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