首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫

MySQL 表達式求值與型別轉換完整解析:運算子優先序、NULL 處理、日期時間解讀規則

     編輯:MySQL 資料庫相關知識

前言

MySQL 允許在 SQL 陳述式中撰寫包含常數、函數呼叫、欄位參考的複雜表達式,廣泛用於 SELECT 選取清單、WHERE 過濾條件、INSERT ... VALUES()、UPDATE ... SET 等場合。理解表達式求值順序、隱含型別轉換規則、NULL 特殊語意,是撰寫正確、高效查詢的基石。本文系統整理運算子分類與優先序、型別轉換矩陣、日期時間解讀邏輯、常見陷阱與測試驗證技巧。

一、表達式構成元素

  • 常數:數值(42)、字串('abc')、十六進位(0x4142)、布林(TRUE/FALSE)
  • 函數呼叫:NOW()、STRCMP('a','b')、CONCAT(col1, col2) — 函數名與左括號間不可有空格
  • 欄位參考:col_name、tbl_name.col_name、db_name.tbl_name.col_name
  • 運算子組合:算術、比較、邏輯、位元、模式比對
  • 括號分組:(expr) 改變求值順序

二、運算子分類與優先序完整表

優先序由高到低(同行同優先序,左結合):

優先序運算子類別
1 (最高)INTERVAL特殊
2BINARY、COLLATE型別轉換/排序規則
3!、-(一元負號)、~(位元反轉)一元運算子
4^位元 XOR
5*、/、%、DIV算術
6+、-算術
7<<、>>位元位移
8&位元 AND
9|位元 OR
10=、<=>、>、>=、<、<=、<>、!=、IS、LIKE、REGEXP、IN比較
11BETWEEN、CASE、WHEN、THEN、ELSE流程控制
12NOT邏輯非
13&&、AND邏輯與
14||、OR邏輯或
15:=指派

關鍵差異:|| 在 MySQL 為邏輯或(非字串串接),字串串接必須用 CONCAT()。ANSI 模式下 || 為串接,可用 SET sql_mode='PIPES_AS_CONCAT' 切換。

三、型別轉換規則矩陣

MySQL 依運算子需求自動轉換運算元型別,核心原則:「以運算子預期型別為準」。

1. 算術/位元/邏輯運算子 → 數值語境

  • 字串 '42' → 數值 42
  • 非數值字串 'abc' → 0(伴隨警告)
  • NULL 參與任何算術/位元運算 → 結果 NULL
  • 邏輯運算視 NULL 為假(0),非零數值為真

2. 字串函數 → 字串語境

  • CONCAT(1,2,3) → '123'(數值轉字串)
  • REPEAT('X', CONCAT(1,2,3)/10) → REPEAT('X', 12.3) → 整除得 12 → 12 個 X

3. 比較運算子的型別解析邏輯

運算元組合比較模式範例結果
兩數值數值比較2 < 11 → 1
兩字串字典序比較'2' < '11' → 0('2' > '1')
數值 + 字串數值比較(字串轉數值)'2' < 11 → 1
含 NULL結果 NULL(除 <=>、IS NULL)NULL = 1 → NULL
TIMESTAMP/DATETIME + 常數時間值比較dt_col < '2025-01-01'
十六進位 + 非數值二進位字串比較0x61 = 'a' → 1

4. 日期時間解讀規則

  • 數值語境下:20250101 → 日期 '2025-01-01'
  • 字串語境下:'2025-01-01'、'20250101'、'250101' 皆可解析
  • TO_DAYS('2025-01-01') = TO_DAYS(20250101) = TO_DAYS(20250101.0)
  • 非法日期 → '0000-00-00'(零日期)

四、NULL 值特殊處理規範

操作類別規則範例
算術/位元運算任何運算元為 NULL → 結果 NULL5 + NULL = NULL
邏輯運算NULL 視為假(0)NULL AND TRUE = 0
比較運算除 <=>、IS NULL、IS NOT NULL 外皆回傳 NULLNULL = NULL → NULL;NULL <=> NULL → 1
函數參數多數函數遇 NULL 回傳 NULL;IFNULL()、COALESCE() 專門處理IFNULL(NULL, 'def') → 'def'
排序ASC 時 NULL 排最前;DESC 時排最後ORDER BY col ASC → NULL 在最上方

五、常見陷阱與除錯技巧

陷阱 1:字串欄位與數值比較導致全表掃描

-- char_col 為 CHAR 型別,含 '00', '01', 'abc'
DELETE FROM t WHERE char_col = 00;  -- 00 視為數值 0
-- 所有非數值字串轉為 0,條件全真,全表被刪!

修正:WHERE char_col = '00' 或 WHERE char_col = '00' + 0 強制字串比較。

陷阱 2:索引欄位包裹在函數中導致索引失效

-- 錯誤:YEAR(date_col) 需逐列計算
SELECT * FROM t WHERE YEAR(date_col) < 1990;
-- 正確:字面日期常數,可用索引
SELECT * FROM t WHERE date_col < '1990-01-01';

陷阱 3:浮點數邏輯判斷

IF(0.3, 'true', 'false')  -- 0.3 轉整數為 0 → 'false'
-- 正確寫法
IF(0.3 > 0, 'true', 'false')  -- 明確比較

除錯利器:SELECT 測試表達式

SELECT 'abc' + 0, '123' + 0, 'abc' = 0, '123' = 0;
SELECT IFNULL(NULL, 'x'), COALESCE(NULL, NULL, 'y');
SELECT 0.3, 0.3 + 0, 0.3 > 0;

強制型別轉換技巧

  • 轉數值:col + 0 或 col * 1 或 CAST(col AS UNSIGNED)
  • 轉字串:CONCAT(col) 或 CAST(col AS CHAR)
  • 轉日期:STR_TO_DATE(col, '%Y%m%d') 或 CAST(col AS DATE)
  • 二進位比較:BINARY col = 'ABC' 或 col = BINARY 'ABC'

六、超範圍與非法值處理原則

  • 數值/時間型別:超範圍值截斷至邊界值
  • 定長字串:過長截斷;ENUM/SET 非法值轉為空串/移除非法子項
  • 日期時間:非法值 → 零值(0000-00-00、00:00:00)
  • ALTER TABLE、LOAD DATA、UPDATE、多列 INSERT 產生的轉換會回傳警告計數,可用 SHOW WARNINGS 或 API mysql_info() 取得

結語

MySQL 的型別系統以「寬容自動轉換」著稱,但這正是 Bug 溫床。掌握運算子優先序、比較模式判定邏輯、NULL 三值邏輯、日期時間解讀規則,並養成關鍵查詢先用 SELECT 驗證表達式結果的習慣,才能寫出穩健、可預測的 SQL。建議在開發規範中明確要求:WHERE 條件運算元型別一致、禁止隱含轉換、日期常數統一用 'YYYY-MM-DD' 格式。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved