top
Loading...
1.8.6.2.對無效數據的約束
1.8.6.2. 對無效數據的約束

在MySQL 5.0.2之前,MySQL對非法或不當值并不嚴厲,而且為了數據輸入還會強制將它們變為合法值。在MySQL 5.0.2和更高版本中,保留了以前的默認行為,但你可以為不良值選擇更傳統的處理方法,從而使得服務器能夠拒絕并放棄出現不良值的語句。本節介紹了MySQL的默認行為(寬大行為),新的嚴格的SQL模式,以及它們的區別。

如果你未使用嚴格模式,下述情況是真實的。如果將“不正確”的值插入到列,如將NULL值插入非NULL列,或將過大的數值插入數值列,MySQL會將這些列設置為“最可能的值”,而不是生成錯誤信息。

·         如果試圖將超范圍的值保存到數值列,MySQL服務器將保存0(最小的可能值)取而代之,或最大的可能值。

·         對于字符串,MySQL或保存空字符串,或將字符串盡可能多的部分保存到列中。

·         如果打算將不是以數值開頭的字符串保存到數值列,MySQL將保存0。

·         MySQL允許將特定的不正確日期值保存到DATE和DATETIME列(如“2000-02-31”或“2000-02-00”)。其觀點在于,驗證日期不是SQL服務器的任務。如果MySQL能保存日期值并準確檢索相同的值,MySQL就能按給定的值保存它。如果日期完全不正確(超出服務器能保存的范圍)將在列中保存特殊的日期值“0000-00-00”取而代之。

·         如果試圖將NULL值保存到不接受NULL值的列,對于單行INSERT語句,將出現錯誤。對于多行INSERT語句或INSERT INTO ... SELECT語句,MySQL服務器會保存針對列數據類型的隱含默認值。一般情況下,對于數值類型,它是0,對于字符串類型,它是空字符串(''),對于日期和時間類型是“zero”。在13.1.5節,“CREATE TABLE語法”一節中,討論了隱含的默認值。

·         如果INSERT語句未為列指定值,如果列定義包含明確的DEFAULT子句,MySQL將插入默認值。如果在定義中沒有這類DEFAULT子句,MySQL會插入列數據類型的隱含默認值。

采用前述規則的原因在于,在語句開始執行前,無法檢查這些狀況。如果在更新了數行后遇到這類問題,我們不能僅靠回滾解決,這是因為存儲引擎可能不支持回滾。中止語句并不是良好的選擇,在該情況下,更新完成了“一半”,這或許是最差的情況。對于本例,較好的方法是“僅可能做到最好”,然后就像什么都未發生那樣繼續。

在MySQL 5.0.2和更高版本中,可以使用STRICT_TRANS_TABLESSTRICT_ALL_TABLES SQL模式,選擇更嚴格的處理方式。請參見5.3.2節,“SQL服務器模式”。

STRICT_TRANS_TABLES的工作方式:

·         對于事務性存儲引擎,在語句中任何地方出現的不良數據值均會導致放棄語句并執行回滾。

·         對于非事務性存儲引擎,如果錯誤出現在要插入或更新的第1行,將放棄語句。(在這種情況下,可以認為語句未改變表,就像事務表一樣)。首行后出現的錯誤不會導致放棄語句。取而代之的是,將調整不良數據值,并給出告警,而不是錯誤。換句話講,使用STRICT_TRANS_TABLES后,錯誤值會導致MySQL執行回滾操作,如果可以,所有更新到此為止。

要想執行更嚴格的檢查,請啟用STRICT_ALL_TABLES。除了非事務性存儲引擎,它與STRICT_TRANS_TABLES等同,即使當不良數據出現在首行后的其他行,所產生的錯誤也會導致放棄語句。這意味著,如果錯誤出現在非事務性表多行插入或更新過程的中途,僅更新部分結果。前面的行將完成插入或更新,但錯誤出現點后面的行則不然。對于非事務性表,為了避免這種情況的發生,可使用單行語句,或者在能接受轉換警告而不是錯誤的情況下使用STRICT_TRANS_TABLES。要想在第1場合防止問題的出現,不要使用MySQL來檢查列的內容。最安全的方式(通常也較快)是,讓應用程序負責,僅將有效值傳遞給數據庫。

有了嚴格的模式選項后,可使用INSERT IGNOREUPDATE IGNORE而不是不帶IGNORE的INSERTUPDATE,將錯誤當作告警對待。

作者:mysql.com
來源:http://dev.mysql.com/doc/refman/5.1/zh/introduction.html
北斗有巢氏 有巢氏北斗