共用方式為


ANSI_MODE

適用於:核取記號為「是」 Databricks SQL

ANSI_MODE 態參數會控制內建函式和轉換作業的主要行為。

本文說明 Databricks SQL 中的 ANSI 模式。 如需 Databricks Runtime 中的 ANSI 合規性,請參閱 Databricks Runtime 中的 ANSI 合規性。

設定

  • TRUE

    遵循 SQL 標準處理特定算術運算和類型轉換的方式,類似於大部分的資料庫和數據倉儲。 遵循此標準可提升更好的數據品質、完整性和可移植性。

  • Databricks SQL 使用 Hive 兼容的行為。

您可以使用 SET 語句,以及在全域層級使用 SQL 組態參數或 SQL 倉儲 API,在會話層級設定此參數。

系統預設

系統預設值適用於 TRUE Databricks SQL 2022.35 和更新版本上新增的帳戶。

詳細描述

Databricks SQL 參考文件說明 SQL 標準行為。

下列各節說明ANSI_MODE TRUE (ANSI 模式) 和 FALSE (非 ANSI 模式) 之間的差異。

操作員

在非 ANSI 模式中,對數值類型執行的算術運算可能會傳回溢值或 NULL,而在 ANSI 模式中,這類作業會傳回錯誤。

Operator 名稱 範例 ANSI_MODE = true ANSI_MODE = false
dividend / divisor 傳回除數除以除數的股息。 1/0 錯誤 NULL
- expr 傳回 expr 的否定值。 -(-128y) 錯誤 -128y (溢位)
expr1 - expr2 傳回 expr1 的 expr2 減法。 -128y - 1y 錯誤 127y (溢位)
expr1 + expr2 傳回 expr1 和 expr2 的總和。 127y + 1y 錯誤 -128y (溢位)
dividend % divisor 傳回除數/除數后的餘數。 1 % 0 錯誤 NULL
multiplier * multiplicand 傳回乘數乘以乘以乘數。 100y * 100y 錯誤 16y (溢位)
arrayExpr[index] 傳回位於索引處之arrayExpr的專案。 無效的陣列索引 錯誤 NULL
mapExpr[key] 傳回索引鍵的 mapExpr 值。 無效的對應索引鍵 錯誤 NULL
divisor div dividend 傳回除數除數除法的整數部分。 1 div 0 錯誤 NULL

函式

某些內建函式的行為在 ANSI 模式與非 ANSI 模式下,在以下指定的條件下可能會有所不同。

Operator 描述 條件 ANSI_MODE = true ANSI_MODE = false
abs(expr) 傳回 expr 中數值的絕對值。 abs(-128y) 錯誤 -128y (溢位)
element_at(mapExpr, key) 傳回索引鍵的 mapExpr 值。 無效的對應索引鍵 錯誤 NULL
element_at(arrayExpr, index) 傳回位於索引處之arrayExpr的專案。 無效的陣列索引 錯誤 NULL
elt(index, 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(dividend, divisor) 傳回除數/除數后的餘數。 mod(1, 0) 錯誤 NULL
next_day(expr,dayOfWeek) 傳回比 expr 晚的第一個日期,並在 dayOfWeek 中命名為 。 一周無效的一天 錯誤 NULL
parse_url(url, partToExtract[, key]) 從 URL 擷取元件。 URL 無效 錯誤 NULL
pmod(dividend, divisor) 傳回除數/除數之後的正餘數。 pmod(1, 0) 錯誤 NULL
size(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 = true ANSI_MODE = false
布林值 時間戳記 cast(TRUE AS TIMESTAMP) 錯誤 1970-01-01 00:00:00.000001 UTC
Date 布林值 cast(DATE'2001-08-09' AS BOOLEAN) 錯誤 NULL
時間戳記 布林值 cast(TIMESTAMP'1970-01-01 00:00:00Z' AS BOOLEAN) 錯誤 FALSE
整數數值 Binary cast(15 AS BINARY) 錯誤 二進位表示法

執行階段錯誤

來源類型 目標類型 Condition 範例 ANSI_MODE = true ANSI_MODE = false
String 非字串 無效的輸入 cast('a' AS INTEGER) 錯誤 NULL
數位、結構、對應 數位、結構、對應 無效的輸入 cast(ARRAY('1','2','3') AS ARRAY<DATE>) 錯誤 NULL
數值 數值 Overflow cast(12345 AS BYTE) 錯誤 NULL
數值 整數數值 截斷 cast(5.1 AS INTEGER) 錯誤 5

注意

對於每個轉換,您可以使用 try_cast 而不是 轉換 來傳回 NULL ,而不是錯誤。

隱含類型強制規則

在 下 ANSI_MODE = TRUE,Databricks SQL 會針對下列專案使用明確的 SQL 數據類型轉換規則

相比之下 ANSI_MODE = FALSE ,這不一致且更加寬大。 例如:

  • 搭配任何算術運算子使用 STRING 型別時,字串會隱含轉換成 DOUBLE
  • 比較 與 STRING 任何數值類型時,字串會隱含轉換成它所比較的類型。
  • 執行UNION、 或其他作業時,如果有任何STRING類型存在,則必須找到最不常見的類型,所有類型都會轉換成 STRING COALESCE

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