SQL Mode 核心作用
定義 MySQL 支援的 SQL 語法規則、數據校驗嚴格程度、錯誤處理行為。可動態調整,無需重啟。
查看與設置
-- 查看當前會話/全局模式
SELECT @@SESSION.sql_mode, @@GLOBAL.sql_mode;
-- 會話級臨時生效
SET SESSION sql_mode = 'STRICT_TRANS_TABLES,NO_ENGINE_SUBSTITUTION';
-- 全局持久化 (需寫入 my.cnf)
[mysqld]
sql_mode = 'STRICT_TRANS_TABLES,NO_ENGINE_SUBSTITUTION,ONLY_FULL_GROUP_BY'
常用模式值對照表
| 模式值 | 行為描述 | 推薦場景 |
STRICT_TRANS_TABLES | 事務表插入非法值直接報錯回滾;非事務表僅首行報錯 | 生產環境必開 |
STRICT_ALL_TABLES | 所有表 (含非事務) 嚴格模式 | 對數據質量極高要求 |
TRADITIONAL | STRICT_TRANS_TABLES + NO_ZERO_DATE + NO_ZERO_IN_DATE + ERROR_FOR_DIVISION_BY_ZERO 組合 | 傳統嚴格模式 |
ANSI | 語法行為向標準 SQL 靠攏 | 異構遷移兼容 |
ONLY_FULL_GROUP_BY | GROUP BY 必須包含所有非聚合列 (5.7+ 默認開啟) | 防止語義模糊查詢 |
NO_ZERO_DATE | 禁止 '0000-00-00' 日期 | 業務不允許空日期 |
NO_ZERO_IN_DATE | 禁止月/日為 0 的日期 (如 '2024-00-01') | 日期完整性校驗 |
ERROR_FOR_DIVISION_BY_ZERO | 除零報錯而非返回 NULL | 計算準確性要求高 |
NO_ENGINE_SUBSTITUTION | 指定引擎不可用時報錯而非靜默降級 | 防止靜默性能退化 |
PIPES_AS_CONCAT | || 作為字符串連接而非 OR | Oracle/PostgreSQL 兼容 |
ANSI_QUOTES | " 作為識別符引號而非字符串引號 | 標準 SQL 兼容 |
IGNORE_SPACE | 允許函數名與括號間有空格 | 兼容舊代碼風格 |
嚴格模式實戰對比
-- 建表
CREATE TABLE t5 (c1 CHAR(3));
-- 默認模式 (寬鬆)
INSERT INTO t5 VALUES('abcd');
-- Query OK, 1 row affected, 1 warning (Data truncated)
SELECT * FROM t5; -- 'abc' (靜默截斷)
-- 開啟 STRICT_TRANS_TABLES
SET SESSION sql_mode = 'STRICT_TRANS_TABLES';
INSERT INTO t5 VALUES('abcd');
-- ERROR 1406 (22001): Data too long for column 'c1' at row 1
異構數據庫兼容模式組合
| 目標數據庫 | 建議 sql_mode 組合 |
| DB2 | PIPES_AS_CONCAT, ANSI_QUOTES, IGNORE_SPACE, NO_KEY_OPTIONS, NO_TABLE_OPTIONS, NO_FIELD_OPTIONS |
| Oracle | PIPES_AS_CONCAT, ANSI_QUOTES, IGNORE_SPACE, NO_KEY_OPTIONS, NO_TABLE_OPTIONS, NO_FIELD_OPTIONS, NO_AUTO_CREATE_USER |
| SQL Server | PIPES_AS_CONCAT, ANSI_QUOTES, IGNORE_SPACE, NO_KEY_OPTIONS, NO_TABLE_OPTIONS, NO_FIELD_OPTIONS |
| PostgreSQL | PIPES_AS_CONCAT, ANSI_QUOTES, IGNORE_SPACE, NO_KEY_OPTIONS, NO_TABLE_OPTIONS, NO_FIELD_OPTIONS |
| MaxDB | PIPES_AS_CONCAT, ANSI_QUOTES, IGNORE_SPACE, NO_KEY_OPTIONS, NO_TABLE_OPTIONS, NO_FIELD_OPTIONS, NO_AUTO_CREATE_USER |
數據校驗與轉換功能
- 日期合法性:
NO_ZERO_DATE + NO_ZERO_IN_DATE 拒絕非法日期
- 除零保護:
ERROR_FOR_DIVISION_BY_ZERO 使 1/0 拋錯
- 識別符引號:
ANSI_QUOTES 讓 "col" 成列名,字符串必須用 'str'
- 關閉轉義:
NO_BACKSLASH_ESCAPES 讓反斜線成普通字符
- 字符串連接:
PIPES_AS_CONCAT 使 'a' || 'b' 等價 CONCAT('a','b')
風險提示
- 非事務引擎 (MyISAM) 下
STRICT_TRANS_TABLES 發生錯誤時,已執行的 DML 無法回滾,導致部分更新
- 老應用遷移時建議:先開啟
sql_mode='' 觀察 Warning,逐步收緊
- 5.7+ 默認已含
ONLY_FULL_GROUP_BY、STRICT_TRANS_TABLES 等,升級前必測