
解決辦法
在 MySQL 5.7 以上版本中,啟用了嚴(yán)格模式。
在配置文件中 /etc/mysql/my.cnf 中找到:
sql-model=STRICT_TRANS_TABLES,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION
修改為:
sql-mode=NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION
然后重啟 MySQL
STRICT_TRANS_TABLES 存儲(chǔ)引擎啟用嚴(yán)格模式,非法數(shù)據(jù)值被拒絕
出現(xiàn)此問(wèn)題的原因
在 MySQL 5.0.2 以前,MySQL 對(duì)非法值檢查并不嚴(yán)厲,而且為了數(shù)據(jù)輸入還會(huì)強(qiáng)制將他們變?yōu)楹戏ㄖ怠?/p>
在 MySQL 5.0.2 以后的版本中,保留了以前的默認(rèn)行為,但你可以為不良值選擇更傳統(tǒng)的處理方法,從而使得服務(wù)器能夠拒絕并放棄出現(xiàn)不良值的語(yǔ)句。
嚴(yán)格模式
如果未使用嚴(yán)格模式,下面的情況是合法的:
1、如果將不正確的值插入到列,如將 null 值插入非 null 列,或?qū)⑦^(guò)大的數(shù)據(jù)插入數(shù)值列,MySQL 會(huì)將這些列設(shè)置為最可能的值,而不是拋出錯(cuò)誤信息。
2、如果視圖將超過(guò)范圍的值保存到數(shù)值列,MySQL 服務(wù)器將保存 0 (最小的可能值) 取而代之,或最大的可能值。
3、對(duì)于字符串,MySQL 或保存空字符串,或?qū)⒆址赡芏嗟牟糠直4娴搅兄小?br>
4、如果打算將不是以數(shù)值開(kāi)頭的字符串保存到數(shù)值列,MySQL 將保存 0 。
5、MySQL 允許將特定的不正確日期值保存到 DATE 和 DATETIME 列(如:2000-02-31 或 2000-02-00)。其觀點(diǎn)在于,驗(yàn)證日期不是 SQL 服務(wù)器的任務(wù)。如果 MySQL 能保存日期值并準(zhǔn)確檢索相同的值,MySQL 就能按給定的值保存它。如果日期完全不正確(超出服務(wù)器能保存的范圍)將在列中保存特殊的日期值 0000-00-00 取而代之。
6、如果視圖將 null 值保存到不接受 null 值的列,對(duì)于單行 insert 語(yǔ)句,將出現(xiàn)錯(cuò)誤。對(duì)于多行 insert 語(yǔ)句或者 insert into ... select 語(yǔ)句,MySQL 服務(wù)器會(huì)保存針對(duì)列數(shù)據(jù)類(lèi)型的隱含默認(rèn)值。一般情況下,對(duì)于數(shù)值類(lèi)型,它是 0,對(duì)于字符串類(lèi)型,它是空字符串(''),對(duì)于日期和時(shí)間類(lèi)型是 zero 。
7、如果 insert 語(yǔ)句未為列指定值,如果列定義包含明確的 default 子句,MySQL 將插入默認(rèn)值。如果在定義中沒(méi)有這類(lèi) default 子句,MySQL 會(huì)插入列數(shù)據(jù)類(lèi)型的隱含默認(rèn)值。
8、采用前描述規(guī)則的原因在于,在語(yǔ)句開(kāi)始執(zhí)行前,無(wú)法檢查這些情況。如果在更新了數(shù)行后遇到這類(lèi)問(wèn)題,我們不能僅靠回滾解決,這是因?yàn)榇鎯?chǔ)引擎可能不支持回滾。中止語(yǔ)句并不是良好的選擇,在該情況下,更新完成了 “一半”,這或許是最差的情況。對(duì)于本例,較好的方式是 “盡可能做到最好”,然后就像什么都沒(méi)有發(fā)生那樣繼續(xù)執(zhí)行。
在 MySQL 5.0.2 以后的版本中,可以使用 STRICT_TRANS_TABLES 或 STRICT_ALL_TABLES SQL 模式,選擇更嚴(yán)格的處理方式。
STRICT_TRANS_TABLES的工作方式:
1、對(duì)于事務(wù)性存儲(chǔ)引擎,在語(yǔ)句中任何地方出現(xiàn)的不良數(shù)據(jù)值均會(huì)導(dǎo)致放棄語(yǔ)句并執(zhí)行回滾。
2、對(duì)于非事務(wù)性存儲(chǔ)引擎,如果錯(cuò)誤出現(xiàn)在要插入或更新的第 1 行,將放棄語(yǔ)句。(在這種情況下,可以認(rèn)為語(yǔ)句未改變表,就像事務(wù)表一樣)。首行后出現(xiàn)的錯(cuò)誤不會(huì)導(dǎo)致放棄語(yǔ)句。取而代之的是,將調(diào)整不良數(shù)據(jù)值,并給出告警,而不是錯(cuò)誤。換句話(huà)講,使用 STRICT_TRANS_TABLES 后,錯(cuò)誤值會(huì)導(dǎo)致 MySQL 執(zhí)行回滾操作,如果可以,所有更新到此為止。
要想執(zhí)行更嚴(yán)格的檢查,請(qǐng)啟用 STRICT_ALL_TABLES。除了非事務(wù)性存儲(chǔ)引擎,它與 STRICT_TRANS_TABLES 等同,即使當(dāng)不良數(shù)據(jù)出現(xiàn)在首行后的其他行,所產(chǎn)生的錯(cuò)誤也會(huì)導(dǎo)致放棄語(yǔ)句。這意味著,如果錯(cuò)誤出現(xiàn)在非事務(wù)性表多行插入或更新過(guò)程的中途,僅更新部分結(jié)果。前面的行將完成插入或更新,但錯(cuò)誤出現(xiàn)點(diǎn)后面的行則不然。對(duì)于非事務(wù)性表,為了避免這種情況的發(fā)生,可使用單行語(yǔ)句,或者在能接受轉(zhuǎn)換警告而不是錯(cuò)誤的情況下使用 STRICT_TRANS_TABLES。要想在第 1 場(chǎng)合防止問(wèn)題的出現(xiàn),不要使用 MySQL 來(lái)檢查列的內(nèi)容。最安全的方式(通常也較快)是,讓?xiě)?yīng)用程序負(fù)責(zé),僅將有效值傳遞給數(shù)據(jù)庫(kù)。
有了嚴(yán)格的模式選項(xiàng)后,可使用 INSERT IGNORE 或 UPDATE IGNORE 而不是不帶 IGNORE 的 INSERT 或 UPDATE,將錯(cuò)誤當(dāng)作告警對(duì)待。