解決辦法
在 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)此問題的原因
在 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án)格模式
如果未使用嚴(yán)格模式鸵钝,下面的情況是合法的:
1糙臼、如果將不正確的值插入到列,如將 null 值插入非 null 列恩商,或?qū)⑦^大的數(shù)據(jù)插入數(shù)值列变逃,MySQL 會(huì)將這些列設(shè)置為最可能的值,而不是拋出錯(cuò)誤信息怠堪。
2揽乱、如果視圖將超過范圍的值保存到數(shù)值列,MySQL 服務(wù)器將保存 0 (最小的可能值) 取而代之粟矿,或最大的可能值凰棉。
3、對(duì)于字符串陌粹,MySQL 或保存空字符串撒犀,或?qū)⒆址赡芏嗟牟糠直4娴搅兄小?br>
4、如果打算將不是以數(shù)值開頭的字符串保存到數(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 語句派桩,將出現(xiàn)錯(cuò)誤。對(duì)于多行 insert 語句或者 insert into ... select 語句蚌斩,MySQL 服務(wù)器會(huì)保存針對(duì)列數(shù)據(jù)類型的隱含默認(rèn)值铆惑。一般情況下,對(duì)于數(shù)值類型送膳,它是 0员魏,對(duì)于字符串類型,它是空字符串('')叠聋,對(duì)于日期和時(shí)間類型是 zero 撕阎。
7、如果 insert 語句未為列指定值碌补,如果列定義包含明確的 default 子句虏束,MySQL 將插入默認(rèn)值。如果在定義中沒有這類 default 子句厦章,MySQL 會(huì)插入列數(shù)據(jù)類型的隱含默認(rèn)值镇匀。
8、采用前描述規(guī)則的原因在于袜啃,在語句開始執(zhí)行前汗侵,無法檢查這些情況。如果在更新了數(shù)行后遇到這類問題群发,我們不能僅靠回滾解決晰韵,這是因?yàn)榇鎯?chǔ)引擎可能不支持回滾。中止語句并不是良好的選擇熟妓,在該情況下雪猪,更新完成了 “一半”,這或許是最差的情況滑蚯。對(duì)于本例浪蹂,較好的方式是 “盡可能做到最好”抵栈,然后就像什么都沒有發(fā)生那樣繼續(xù)執(zhí)行。
在 MySQL 5.0.2 以后的版本中坤次,可以使用 STRICT_TRANS_TABLES 或 STRICT_ALL_TABLES SQL 模式古劲,選擇更嚴(yán)格的處理方式。
STRICT_TRANS_TABLES的工作方式:
1缰猴、對(duì)于事務(wù)性存儲(chǔ)引擎产艾,在語句中任何地方出現(xiàn)的不良數(shù)據(jù)值均會(huì)導(dǎo)致放棄語句并執(zhí)行回滾。
2滑绒、對(duì)于非事務(wù)性存儲(chǔ)引擎闷堡,如果錯(cuò)誤出現(xiàn)在要插入或更新的第 1 行,將放棄語句疑故。(在這種情況下杠览,可以認(rèn)為語句未改變表,就像事務(wù)表一樣)纵势。首行后出現(xiàn)的錯(cuò)誤不會(huì)導(dǎo)致放棄語句踱阿。取而代之的是,將調(diào)整不良數(shù)據(jù)值钦铁,并給出告警软舌,而不是錯(cuò)誤。換句話講牛曹,使用 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)致放棄語句。這意味著躬拢,如果錯(cuò)誤出現(xiàn)在非事務(wù)性表多行插入或更新過程的中途躲履,僅更新部分結(jié)果。前面的行將完成插入或更新聊闯,但錯(cuò)誤出現(xiàn)點(diǎn)后面的行則不然工猜。對(duì)于非事務(wù)性表,為了避免這種情況的發(fā)生菱蔬,可使用單行語句篷帅,或者在能接受轉(zhuǎn)換警告而不是錯(cuò)誤的情況下使用 STRICT_TRANS_TABLES史侣。要想在第 1 場合防止問題的出現(xiàn),不要使用 MySQL 來檢查列的內(nèi)容魏身。最安全的方式(通常也較快)是惊橱,讓應(yīng)用程序負(fù)責(zé),僅將有效值傳遞給數(shù)據(jù)庫箭昵。
有了嚴(yán)格的模式選項(xiàng)后税朴,可使用 INSERT IGNORE 或 UPDATE IGNORE 而不是不帶 IGNORE 的 INSERT 或 UPDATE,將錯(cuò)誤當(dāng)作告警對(duì)待家制。