文件首頁
MySQL 8.4 參考手冊
相關文件 下載本手冊
PDF (US Ltr) - 39.9Mb
PDF (A4) - 40.0Mb
Man Pages (TGZ) - 258.5Kb
Man Pages (Zip) - 365.5Kb
Info (Gzip) - 4.0Mb
Info (Zip) - 4.0Mb


MySQL 8.4 參考手冊  /  函數與運算子  /  表達式求值中的型別轉換

14.3 表達式求值中的型別轉換

當運算子與不同類型的運算元一起使用時,會發生型別轉換,以使運算元相容。某些轉換會隱式發生。例如,MySQL 會在必要時自動將字串轉換為數字,反之亦然。

mysql> SELECT 1+'1';
        -> 2
mysql> SELECT CONCAT(2,' test');
        -> '2 test'

也可以使用 CAST() 函數將數字明確轉換為字串。使用 CONCAT() 函數會隱式發生轉換,因為它預期字串引數。

mysql> SELECT 38.8, CAST(38.8 AS CHAR);
        -> 38.8, '38.8'
mysql> SELECT 38.8, CONCAT(38.8);
        -> 38.8, '38.8'

請參閱本節稍後內容,以了解隱式數字到字串轉換的字元集資訊,以及適用於 CREATE TABLE ... SELECT 陳述式的修改規則。

以下規則說明如何對比較運算進行轉換

  • 如果一個或兩個引數為 NULL,則比較的結果為 NULL,但 NULL 安全的 <=> 相等比較運算子除外。對於 NULL <=> NULL,結果為 true。不需要轉換。

  • 如果比較運算中的兩個引數都是字串,則會將它們作為字串進行比較。

  • 如果兩個引數都是整數,則會將它們作為整數進行比較。

  • 如果十六進位值未與數字比較,則會將它們視為二進位字串。

  • 如果其中一個引數是 TIMESTAMPDATETIME 資料行,而另一個引數是常數,則會在執行比較之前將常數轉換為時間戳記。這樣做是為了更符合 ODBC 的要求。這不會對 IN() 的引數執行。為了安全起見,在進行比較時,請務必使用完整的日期時間、日期或時間字串。例如,當將 BETWEEN 與日期或時間值搭配使用時,為了獲得最佳結果,請使用 CAST() 將值明確轉換為所需的資料類型。

    來自一個或多個表格的單列子查詢不被視為常數。例如,如果子查詢傳回要與 DATETIME 值進行比較的整數,則比較將作為兩個整數執行。該整數不會轉換為時間值。若要將運算元作為 DATETIME 值進行比較,請使用 CAST() 將子查詢值明確轉換為 DATETIME

  • 如果其中一個引數是十進位值,則比較取決於另一個引數。如果另一個引數是十進位或整數值,則會將引數作為十進位值進行比較;如果另一個引數是浮點值,則會將引數作為浮點值進行比較。

  • 在所有其他情況下,會將引數作為浮點數 (雙精度) 進行比較。例如,字串和數值運算元的比較將作為浮點數的比較進行。

如需有關將值從一個時間類型轉換為另一個時間類型的資訊,請參閱 第 13.2.8 節,「日期和時間類型之間的轉換」

JSON 值的比較分為兩個層次。第一個層次的比較基於被比較值的 JSON 類型。如果類型不同,比較結果僅取決於哪個類型具有較高的優先順序。如果兩個值具有相同的 JSON 類型,則會使用特定於類型的規則進行第二層次的比較。對於 JSON 和非 JSON 值的比較,非 JSON 值會被轉換為 JSON,然後以 JSON 值進行比較。詳情請參閱JSON 值的比較和排序

以下範例說明字串在比較運算中如何轉換為數字

mysql> SELECT 1 > '6x';
        -> 0
mysql> SELECT 7 > '6x';
        -> 1
mysql> SELECT 0 > 'x6';
        -> 0
mysql> SELECT 0 = 'x6';
        -> 1

當字串欄位與數字比較時,MySQL 無法使用該欄位的索引來快速查找值。如果 str_col 是一個已索引的字串欄位,則在執行以下語句中的查找時無法使用索引

SELECT * FROM tbl_name WHERE str_col=1;

原因是有許多不同的字串可以轉換為值 1,例如 '1'' 1''1a'

浮點數與 INTEGER 類型的大值之間的比較是近似的,因為整數在比較之前會轉換為雙精度浮點數,而雙精度浮點數無法精確表示所有 64 位元的整數。例如,整數值 253 + 1 無法表示為浮點數,並且在進行浮點數比較之前會根據平台四捨五入為 253 或 253 + 2。

為了說明這一點,以下比較中只有第一個比較是比較相等的值,但兩個比較都會返回 true (1)

mysql> SELECT '9223372036854775807' = 9223372036854775807;
        -> 1
mysql> SELECT '9223372036854775807' = 9223372036854775806;
        -> 1

當從字串轉換為浮點數和從整數轉換為浮點數時,它們不一定以相同的方式發生。整數可能會由 CPU 轉換為浮點數,而字串則是以逐位數的方式進行轉換,其中涉及浮點數乘法。此外,結果可能會受到諸如電腦架構或編譯器版本或優化級別等因素的影響。避免此類問題的一種方法是使用 CAST(),這樣值就不會隱式轉換為浮點數。

mysql> SELECT CAST('9223372036854775807' AS UNSIGNED) = 9223372036854775806;
        -> 0

有關浮點數比較的更多資訊,請參閱第 B.3.4.8 節,「浮點數值的問題」

伺服器包含 dtoa,這是一個轉換函式庫,為改進字串或 DECIMAL 值與近似值(FLOAT/DOUBLE)數字之間的轉換提供了基礎。

  • 跨平台轉換結果的一致性,例如消除了 Unix 與 Windows 之間的轉換差異。

  • 在先前結果未提供足夠精度的情況下(例如,接近 IEEE 極限的值)能精確表示值。

  • 將數字轉換為具有最佳可能精度的字串格式。dtoa 的精度始終與標準 C 函式庫的精度相同或更高。

因為此函式庫產生的轉換在某些情況下與非 dtoa 結果不同,因此依賴先前結果的應用程式可能存在不相容的潛在風險。例如,依賴先前轉換的特定精確結果的應用程式可能需要調整以適應額外的精度。

dtoa 函式庫提供的轉換具有以下屬性。D 表示具有 DECIMAL 或字串表示的值,而 F 表示原生二進位 (IEEE) 格式的浮點數。

  • F -> D 轉換以最佳可能的精度完成,返回 D 作為最短的字串,當讀回並四捨五入到 IEEE 指定的原生二進位格式中最接近的值時,會產生 F

  • D -> F 轉換的完成方式是 F 是輸入十進位字串 D 最接近的原生二進位數。

這些屬性表示,除非 F-inf+infNaN,否則 F -> D -> F 轉換是無損的。後者值不受支援,因為 SQL 標準將它們定義為 FLOATDOUBLE 的無效值。

對於 D -> F -> D 轉換,無損的充分條件是 D 使用 15 位或更少的精度位數,不是非正規值、-inf+infNaN。在某些情況下,即使 D 的精度超過 15 位,轉換也是無損的,但情況並非總是如此。

將數值或時間值隱式轉換為字串會產生一個具有由 character_set_connectioncollation_connection 系統變數決定的字元集和校對規則的值。(這些變數通常使用 SET NAMES 設定。有關連線字元集的資訊,請參閱第 12.4 節,「連線字元集和校對規則」。)

這表示這種轉換會產生字元(非二進位)字串(CHARVARCHARLONGTEXT 值),除非連線字元集設定為 binary。在這種情況下,轉換結果是二進位字串(BINARYVARBINARYLONGBLOB 值)。

對於整數運算式,前面關於運算式評估的說明在運算式指派方面有所不同;例如,在如下語句中

CREATE TABLE t SELECT integer_expr;

在這種情況下,運算式產生的欄位中的表格類型為 INTBIGINT,具體取決於整數運算式的長度。如果運算式的最大長度不適合 INT,則改為使用 BIGINT。長度取自 SELECT 結果集中繼資料的 max_length 值(請參閱 C API 基本資料結構)。這表示您可以透過使用足夠長的運算式來強制使用 BIGINT 而非 INT

CREATE TABLE t SELECT 000000000000000000000;