數據庫遷移後出現 ERROR 1366 (HY000): Incorrect integer value: '' for column 'shunxu' at row 1,本文從遷移場景切入,系統分析默認值、嚴格模式、應用參數三方交互機制。
STRICT_TRANS_TABLES)shunxu INT DEFAULT NULL 列傳入空字符串 ''| 方案 | 操作 | 優點 | 缺點 | 風險 |
|---|---|---|---|---|
| 修改默認值 (推薦) | ALTER TABLE doc_main MODIFY shunxu INT NOT NULL DEFAULT 0; | 根治、無應用改動、符合嚴格模式 | 需鎖表、歷史 NULL 變 0 | 低 |
| 應用層轉換 | 空串 → NULL/0 | 邏輯清晰、數據庫無變更 | 需代碼發布、多處修改 | 中 |
| 關閉嚴格模式 | sql_mode 移除 STRICT_TRANS_TABLES | 零改動、快速恢復 | 掩蓋數據質量問題、違規規範 | 高 |
| 列允許 NULL + 默認 0 | ALTER TABLE doc_main MODIFY shunxu INT DEFAULT 0; | 兼容 NULL 語義 | 應用仍可能傳空串報錯 | 中 |
-- 場景 1: NOT NULL DEFAULT 0
INSERT INTO t (col) VALUES (); -- ✅ 存 0
INSERT INTO t (col) VALUES (NULL); -- ❌ ERROR 1048
INSERT INTO t (col) VALUES (''); -- ❌ ERROR 1366 (嚴格模式)
-- 場景 2: DEFAULT 0 (允許 NULL)
INSERT INTO t (col) VALUES (); -- ✅ 存 0
INSERT INTO t (col) VALUES (NULL); -- ✅ 存 NULL
INSERT INTO t (col) VALUES (''); -- ❌ ERROR 1366 (嚴格模式)
-- 場景 3: DEFAULT NULL
INSERT INTO t (col) VALUES (); -- ✅ 存 NULL
INSERT INTO t (col) VALUES (NULL); -- ✅ 存 NULL
INSERT INTO t (col) VALUES (''); -- ❌ ERROR 1366 (嚴格模式)
結論:嚴格模式下,空字符串永遠無法隱式轉換為數值類型,必須在應用層或觸發器中轉換。
DELIMITER //
CREATE TRIGGER tr_doc_main_bi BEFORE INSERT ON doc_main
FOR EACH ROW
BEGIN
IF NEW.shunxu = '' OR NEW.shunxu IS NULL THEN
SET NEW.shunxu = 0;
END IF;
END//
DELIMITER ;
-- 同理 BEFORE UPDATE 觸發器
優點:攔截所有寫入路徑 (應用、手動、ETL);缺點:隱式邏輯、性能微損、調試困難。
SELECT @@sql_mode; 對比源目標環境差異SELECT TABLE_NAME, COLUMN_NAME, COLUMN_DEFAULT, IS_NULLABLE FROM INFORMATION_SCHEMA.COLUMNS WHERE DATA_TYPE IN ('int','bigint','tinyint','smallint','mediumint') AND COLUMN_DEFAULT IS NULL;SET SESSION sql_mode='' 運行 1 週,收集 SHOW WARNINGS 定位問題ALTER TABLE ... MODIFY ... NOT NULL DEFAULT 0 腳本,維護窗口執行
-- 錯誤
ERROR 1366 (HY000): Incorrect string value: '\xD0\xC2...' for column 'name'
-- 根因:連接字符集 GBK,列字符集 UTF8,存入中文
-- 修復
ALTER TABLE tbname CONVERT TO CHARACTER SET gbk; -- 或 utf8mb4
-- 根治:應用/連接/表/列 全鏈路 utf8mb4
遷移升級暴露的 1366 錯誤,本質是「非嚴格模式養成的惡習遇上嚴格模式的審判」。修正默認值約束、補齊應用驗證、建立嚴格模式基線,將遷移危機轉化為數據質量治理的契機。