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

MySQL DATE_FORMAT 內置字符集導致 Illegal mix of collations 錯誤分析與解決

     編輯:MySQL 資料庫相關知識

對比 DATE_FORMAT() 與 TIMEDIFF() 時觸發 ERROR 1267: Illegal mix of collations (utf8_general_ci,COERCIBLE) and (latin1_swedish_ci,NUMERIC) for operation '>'。本文深度解析 DATE_FORMAT 返回值攜帶連接層字符集屬性、TIMEDIFF 返回二進制字符串的機制差異,給出 CONVERT 顯式轉換與會話級字符集統一兩種解決路徑。

現場還原

SELECT DATE_FORMAT('2013-11-19','%Y-%m-%d') > TIMEDIFF('2013-11-19', '2013-11-20');
-- ERROR 1267 (HY000): Illegal mix of collations ... for operation '>'

根因分析:字符集屬性不匹配

1. 官方文檔定性

DATE_FORMAT() returns a string with a character set and collation given by character_set_connection and collation_connection so that it can return month and weekday names containing non-ASCII characters.

TIMEDIFF() 無此說明,返回 binary 字符集。

2. 實測驗證

SET NAMES utf8;
SELECT CHARSET(DATE_FORMAT('2013-11-19','%Y-%m-%d')), CHARSET(TIMEDIFF('2013-11-19', '2013-11-20'));
-- 結果:utf8 | binary

SET NAMES gb2312;
SELECT CHARSET(DATE_FORMAT('2013-11-19','%Y-%m-%d')), CHARSET(TIMEDIFF('2013-11-19', '2013-11-20'));
-- 結果:gb2312 | binary

結論:DATE_FORMAT 結果字符集隨 character_set_connection 變化;TIMEDIFF 固定 binary。比較操作時,MySQL 嘗試隱式轉換失敗,拋出 collation 混合錯誤。

解決方案

方案一:顯式轉換右側操作數 (推薦、精準)

SELECT DATE_FORMAT('2013-11-19','%Y-%m-%d') > 
       CONVERT(TIMEDIFF('2013-11-19', '2013-11-20') USING utf8);
-- 成功返回 1

也可用 CAST(... AS CHAR CHARACTER SET utf8)。

方案二:統一會話字符集 (全局、一次性)

SET NAMES utf8mb4 COLLATE utf8mb4_unicode_ci;
-- 或在 my.cnf [client]/[mysql] 設置 default-character-set
-- 則 DATE_FORMAT 返回 utf8mb4,TIMEDIFF 仍為 binary,但比較時隱式轉換規則不同,實測 8.0+ 可通過

⚠️ 5.7 及以下版本即使統一會話字符集,binary 與具體 collation 比較仍可能報錯,**方案一最通用穩健**。

DATE_FORMAT 格式化符號完整參考表

符號含義示例
%S, %s秒 (00-59)05
%i分 (00-59)30
%H小時 24制 (00-23)14
%h, %I小時 12制 (01-12)02
%k小時 24制 (0-23)14
%l小時 12制 (1-12)2
%T時間 24制 (HH:MM:SS)14:30:05
%r時間 12制 (HH:MM:SS AM/PM)02:30:05 PM
%pAM/PMPM
%W星期全名Sunday
%a星期縮寫Sun
%d月內天數 (01-31)19
%e月內天數 (1-31)19
%D帶英文後綴19th
%w星期索引 (0=Sunday)0
%j年內天數 (001-366)323
%U周數 (00-53, Sunday第一天)46
%u周數 (00-53, Monday第一天)46
%M月份全名November
%b月份縮寫Nov
%m月份 (01-12)11
%c月份 (1-12)11
%Y年份 4位2013
%y年份 2位13
%%字面 %%

總結

DATE_FORMAT 返回值攜帶連接字符集屬性,TIMEDIFF 等時間函數返回 binary,混合比較觸發 collation 衝突。**顯式 CONVERT(... USING charset) 是最精準、版本通用的解法**。開發規範建議:SQL 中涉及字符串與時間/數值比較時,統一顯式 CAST/CONVERT,消除隱式轉換風險。

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