| 組合模式 | 包含的單項模式 |
ANSI | REAL_AS_FLOAT, PIPES_AS_CONCAT, ANSI_QUOTES, IGNORE_SPACE |
TRADITIONAL | STRICT_TRANS_TABLES, STRICT_ALL_TABLES, NO_ZERO_IN_DATE, NO_ZERO_DATE, ERROR_FOR_DIVISION_BY_ZERO, NO_AUTO_CREATE_USER |
ORACLE | PIPES_AS_CONCAT, ANSI_QUOTES, IGNORE_SPACE, NO_KEY_OPTIONS, NO_TABLE_OPTIONS, NO_FIELD_OPTIONS, NO_AUTO_CREATE_USER |
DB2 | PIPES_AS_CONCAT, ANSI_QUOTES, IGNORE_SPACE, NO_KEY_OPTIONS, NO_TABLE_OPTIONS, NO_FIELD_OPTIONS |
版本演進關鍵點
- MySQL 5.6:默認
NO_ENGINE_SUBSTITUTION
- MySQL 5.7:默認
ONLY_FULL_GROUP_BY, STRICT_TRANS_TABLES, NO_ZERO_IN_DATE, NO_ZERO_DATE, ERROR_FOR_DIVISION_BY_ZERO, NO_AUTO_CREATE_USER, NO_ENGINE_SUBSTITUTION
- MySQL 8.0:默認同 5.7,
NO_AUTO_CREATE_USER 移除(已內建)
生產環境推薦配置
[mysqld]
# 核心嚴格模式
sql_mode = STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION
# 日期嚴格控制(視業務兼容性決定是否開啟)
# sql_mode = ...,NO_ZERO_DATE,NO_ZERO_IN_DATE
# 群組查詢規範(5.7+ 默認開啟,舊應用可能需關閉)
# ONLY_FULL_GROUP_BY
常見坑與排查
- 「Data truncated」Warning 變 Error:開啟嚴格模式後,字符串超長、數值越界會直接報錯
- GROUP BY 語義變化:
ONLY_FULL_GROUP_BY 要求 SELECT 列必須出現在 GROUP BY 或聚合函數中
- 日期零值插入失敗:舊代碼插入
'0000-00-00' 需改用 NULL 或有效日期
- 主從複製不一致:主從
sql_mode 必須一致,否則同步報錯
動態調整與驗證
-- 會話級臨時調整(測試用)
SET SESSION sql_mode = 'STRICT_TRANS_TABLES,NO_ZERO_DATE';
-- 全局永久調整(需配置文件持久化)
SET GLOBAL sql_mode = 'STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION';
-- 查看當前模式
SELECT @@sql_mode;
SHOW VARIABLES LIKE 'sql_mode';
最佳實踐:新項目從 5.7/8.0 默認嚴格模式開始,避免歷史包袱;老項目升級前務必全量掃描 SQL、測試數據遷移,分階段開啟嚴格項。
- 上一篇文章: MySQL 預處理語句性能實測:是否真能提升查詢效率?
- 下一篇文章: MySQL 分表唯一 ID 生成方案:基於 LAST_INSERT_ID 的集中式 ID 服務
Copyright ©
程式碼之家 All Rights Reserved