適用於:
Databricks SQL
設定參數 ANSI_MODE 會控制內建函式和轉換作業的關鍵行為。
本文說明 Databricks SQL 中的 ANSI 模式。 如需 Databricks Runtime 中的 ANSI 合規性,請參閱 Databricks Runtime 中的 ANSI 合規性。
設定
真
遵循 SQL 標準處理特定算術運算和類型轉換的方式,類似於大部分的資料庫和數據倉儲。 遵循此標準可提升更好的數據品質、完整性和可移植性。
假
Databricks SQL 使用與 Hive 相容的行為。
您可以在會話層級使用 SET 語句 設定此參數,或在全域層級使用 SQL 組態參數 或 SQL Warehouse API設定此參數。
系統預設
對於在 2022 年 10 月 19 日當天或之後創建的帳戶,系統預設為 TRUE.
詳細描述
Databricks SQL 參考文件說明 SQL 標準行為。
下列各節說明 ANSI_MODETRUE(ANSI 模式)與 FALSE(非 ANSI 模式)之間的差異。
操作員
在非 ANSI 模式中,對數值類型執行的算術運算可能會傳回溢值或 NULL,而在 ANSI 模式中,這類作業會傳回錯誤。
| 操作員 | 名稱 | 範例 | ANSI_MODE = 真 | ANSI_MODE = 假 |
|---|---|---|---|---|
| 股息 / 除數 | 傳回除數除以除數的股息。 | 1/0 |
錯誤 | NULL |
| - expr | 傳回 expr 的否定值。 | -(-128y) |
錯誤 |
-128y (溢位) |
| EXPR1 - EXPR2 | 傳回 expr1 減去 expr2 的結果。 | -128y - 1y |
錯誤 |
127y (溢位) |
| expr1 + expr2 | 傳回 expr1 和 expr2 的總和。 | 127y + 1y |
錯誤 |
-128y (溢位) |
| 股息 % 除數 | 傳回除數/除數后的餘數。 | 1 % 0 |
錯誤 | NULL |
| 乘數 * 乘數 | 傳回乘數乘以被乘數。 | 100y * 100y |
錯誤 |
16y (溢位) |
| arrayExpr[索引] | 傳回位於索引處之 arrayExpr 的元素。 | 無效的陣列索引 | 錯誤 | NULL |
| mapExpr[鍵] | 傳回對應於鍵值的 mapExpr 值。 | 無效的映射鍵 | 錯誤 | NULL |
| 除數 DIV 股息 | 傳回除數除數除法的整數部分。 | 1 div 0 |
錯誤 | NULL |
Functions
某些內建函式的行為在 ANSI 模式與非 ANSI 模式下,在以下指定的條件下可能會有所不同。
| 操作員 | 名稱 | 狀況 | ANSI_MODE = 真 | ANSI_MODE = 假 |
|---|---|---|---|---|
| 絕對值 (EXPR) | 傳回 expr 中數值的絕對值。 | abs(-128y) |
錯誤 |
-128y (溢位) |
| element_at(mapExpr,金鑰) | 傳回對應於鍵值的 mapExpr 值。 | 無效的映射鍵 | 錯誤 | NULL |
| element_at(arrayExpr, index) | 傳回位於索引處之 arrayExpr 的元素。 | 無效的陣列索引 | 錯誤 | NULL |
| elt(索引,expr1 [, ...] ) | 傳回第 n 個運算式。 | 無效的索引 | 錯誤 | NULL |
| make_date(y,m,d) | 從年份、月和日欄位建立日期。 | 無效的結果日期 | 錯誤 | NULL |
| make_timestamp(y,m,d,h,mi,s[,tz]) | 從欄位建立時間戳。 | 無效的結果時間戳 | 錯誤 | NULL |
| make_interval(y,m,w,d,h,mi,s) | 從欄位建立區間。 | 無效的結果間隔 | 錯誤 | NULL |
| mod(被除數、除數) | 傳回除數/除數后的餘數。 | mod(1, 0) |
錯誤 | NULL |
| next_day(expr,dayOfWeek) | 傳回比 expr 晚的第一個日期,並在 dayOfWeek 中命名為 。 | 一周無效的一天 | 錯誤 | NULL |
| parse_url(url, partToExtract[, key]) | 從 URL 擷取部分。 | URL 無效 | 錯誤 | NULL |
| pmod(被除數、除數) | 傳回被除數/除數之後的正餘數。 | pmod(1, 0) |
錯誤 | NULL |
| 大小 (expr) | 傳回 expr 的基數。 | size(NULL) |
NULL |
-1 |
| to_date(expr[,fmt]) | 將 expr 使用自選的格式轉換成日期格式並傳回。 | 無效的 expr 或格式字串 | 錯誤 | NULL |
| to_timestamp(expr[,fmt]) | 使用可選格式將 expr 轉型為時間戳記並傳回。 | 無效的 expr 或格式字串 | 錯誤 | NULL |
| to_unix_timestamp(expr[,fmt]) | 以 UNIX 時間戳的形式傳回 expr 中的時間戳。 | 無效的 expr 或格式字串 | 錯誤 | NULL |
| unix_timestamp([expr[, fmt]]) | 傳回目前或指定時間的 UNIX 時間戳。 | 無效的 expr 或格式字串 | 錯誤 | NULL |
轉型規則
關於 CAST 的規則和行為在 ANSI 模式中更嚴格。 它們可以分成下列三個類別:
編譯時間轉換規則
| 來源類型 | 目標類型 | 範例 | ANSI_MODE = 真 | ANSI_MODE = 假 |
|---|---|---|---|---|
| 布林值 | 時間戳記 | cast(TRUE AS TIMESTAMP) |
錯誤 | 1970-01-01 00:00:00.000001 UTC |
| 日期 | 布林值 | cast(DATE'2001-08-09' AS BOOLEAN) |
錯誤 | NULL |
| 時間戳記 | 布林值 | cast(TIMESTAMP'1970-01-01 00:00:00Z' AS BOOLEAN) |
錯誤 | FALSE |
| 整數數值 | 二進制 | cast(15 AS BINARY) |
錯誤 | 二進位表示法 |
執行階段錯誤
| 來源類型 | 目標類型 | 狀況 | 範例 | ANSI_MODE = 真 | ANSI_MODE = 假 |
|---|---|---|---|---|---|
| 字串 | 非字串 | 無效的輸入 | cast('a' AS INTEGER) |
錯誤 | NULL |
| 陣列、結構體、映射 | 陣列、結構體、映射 | 無效的輸入 | cast(ARRAY('1','2','3') AS ARRAY<DATE>) |
錯誤 | NULL |
| 數字型 | 數字型 | 溢出 | cast(12345 AS BYTE) |
錯誤 | NULL |
| 數字型 | 整數數值 | 截斷 | cast(5.1 AS INTEGER) |
錯誤 | 5 |
隱含類型強制規則
在 下 ANSI_MODE = TRUE,Databricks SQL 會針對下列專案使用明確的 SQL 數據類型轉換規則 :
相比之下,ANSI_MODE = FALSE 前後不一,且更加寬鬆。 例如:
- 搭配任何算術運算子使用
STRING型別時,字串會隱含轉換成DOUBLE。 - 比較 與
STRING任何數值類型時,字串會隱含轉換成它所比較的類型。 - 執行
UNION、COALESCE或其他作業時,如果有任何STRING類型存在,則必須找到最小公共型別,所有類型都會轉換成STRING。
Databricks 建議使用明確 轉換 或 try_cast 函式,而不是依賴 ANSI_MODE = FALSE。
範例
> SET ansi_mode = true;
-- Protects against integral numeric overflow
> SELECT cast(12345 AS TINYINT);
Casting 12345 to tinyint causes overflow
-- For invalid values raises errors instead of returning NULL.
> SELECT cast('a' AS INTEGER);
Invalid input syntax for type numeric: a.
To return NULL instead, use 'try_cast'
-- try_cast() is consistent for both modes
> SELECT try_cast('a' AS INTEGER);
NULL
-- Does not allow ambiguous crosscasting.
> SELECT c1 + c2 FROM VALUES('5', '7.6') AS T(c1, c2);
Cannot resolve '(T.c1 + T.c2)' due to data type mismatch:
'(T.c1 + T.c2)' requires (numeric or interval day to second or interval year to month or interval) type, not string
-- Promotes STRING to least common type (STRING, INTEGER --> BIGINT) for arithmetic operation.
> SELECT typeof(5 - '3');
bigint
-- Promotes STRING to least common type (INTEGER, STRING --> BIGINT) with runtime check
> SELECT c1 = c2 FROM VALUES(10, '10.1') AS T(c1, c2);
Invalid input syntax for type numeric: 10.1. To return NULL instead, use 'try_cast'.
-- Promotes STRING to least common type (STRING, INTEGER --> BIGINT) for set operation with runtime check.
> SELECT typeof(c1) FROM (SELECT 5 UNION ALL SELECT '6') AS T(c1);
bigint
bigint
> SET ansi_mode = false;
-- Silent integral numeric overflow
> SELECT cast(12345 AS TINYINT);
57
-- Returns NULL instead of an error
> SELECT cast('a' AS INTEGER);
NULL
-- try_cast() is safe for both modes
> SELECT try_cast('a' AS INTEGER);
NULL
-- Does allow ambiguous crosscasting using DOUBLE.
> SELECT c1 + c2 FROM VALUES('5', '7.6') AS T(c1, c2);
12.6
-- Crosscasts STRING to DOUBLE for arithmetic operation.
> SELECT typeof(5 - '3');
double
-- Implicitly casts STRING to INTEGER equating 10 with 10.1
> SELECT c1 = c2 FROM VALUES(10, '10.1') AS T(c1, c2);
true
-- Promotes to string for set operations
> SELECT typeof(c1) FROM (SELECT 5 UNION ALL SELECT '6') AS T(c1);
string
string