MySQL 5.0.2+ 默認開啟 STRICT_TRANS_TABLES sql_mode,導致自增主鍵列顯式插入 NULL/0/DEFAULT 時不再自動生成值,改為報錯 Incorrect integer value 或 Field 'id' doesn't have a default value。本文給出定位與修正方案。
CREATE TABLE t (id INT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(10));
INSERT INTO t (name) VALUES ('test'); -- 正常
-- 但某些框架/代碼生成如下語句:
INSERT INTO t (id, name) VALUES (NULL, 'test'); -- 報錯
INSERT INTO t (id, name) VALUES (0, 'test'); -- 報錯
INSERT INTO t (id, name) VALUES (DEFAULT, 'test'); -- 報錯
my.ini 默認配置:
sql-mode="STRICT_TRANS_TABLES,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION"
STRICT_TRANS_TABLES:嚴格模式下,整數列不接受 NULL/0/DEFAULT 作為隱式自增值,**必須省略該列**或顯式指定合法整數。
[mysqld]
# sql-mode="STRICT_TRANS_TABLES,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION"
sql-mode="NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION"
# 重啟 mysqld 生效
INSERT INTO t (name) VALUES ('test');NULL **僅在非嚴格模式下生效**@GeneratedValue、MyBatis useGeneratedKeys、JPA GenerationType.IDENTITY 均會自動省略列| 模式 | 作用 | 建議 |
|---|---|---|
STRICT_TRANS_TABLES | 事務表嚴格模式:非法值報錯而非警告+截斷 | 生產建議開啟,配合代碼規範 |
STRICT_ALL_TABLES | 所有表嚴格模式 | 同左 |
NO_AUTO_CREATE_USER | 禁止 GRANT 隱式創建用戶 | 保留(安全) |
NO_ENGINE_SUBSTITUTION | 指定引擎不可用時不自動替換、報錯 | 保留(防患) |
ONLY_FULL_GROUP_BY | SELECT 非聚合列必須出現在 GROUP BY | 8.0 默認開啟,建議保留 |
NO_ZERO_DATE/NO_ZERO_IN_DATE | 禁止 '0000-00-00' 日期 | 保留(數據質量) |
mysql> SELECT @@sql_mode;
-- 應不含 STRICT_TRANS_TABLES
INSERT INTO t (id, name) VALUES (NULL, 'test'); -- 應成功,id 自增
INSERT INTO t (id, name) VALUES (0, 'test'); -- 應成功(0 視同 NULL)
INSERT INTO t (id, name) VALUES (DEFAULT, 'test'); -- 應成功
「嚴格模式 + 代碼規範」是正道;若歷史代碼量大難以改造,移除 STRICT_TRANS_TABLES 可作過渡,但需承擔數據質量下降風險(如空字符串入數值列變 0、截斷不報錯)。