最近在作一個項目的時候錯了一個至關奇怪的問題:mysql
代碼是我從svn上直接checkout出來的,數據庫是從別人的機器上直接dump出來的。環境配置穩當之後,就是在個人機器上不能正常下訂單。剛開始不明白,爲何一樣的代碼,一樣的數據庫sql
在別人的機器上能夠正常的運行,在個人機器上卻一直不能正常運行。數據庫
之因此出現這樣的問題,緣由是我機器上mysql是以sql-mode="STRICT_TRANS_TABLES,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION"的模式運行的,由於咱們公司產品sql寫的不是特別標準,導致的sql語句不能正常的insert到數據庫,最後致使結果下單提示失敗。服務器
爲了簡單起見,我只是修改了我機器上mysql的sql-model爲"NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION",而後重啓下msyql服務器就OK了。svn
讓我很火大的人寫咱們公司系統的這些NB人士們,既然數據庫表字段定義的是NOT NULL,爲何在寫insert的時候不爲該字段設置默認值?? 不爲字段設置default 還不在sql中給出初始值,不知道這些NB人士們想幹什麼??函數
我但願那些NB人士們,在寫sql的時候能寫的稍微規範一點,至少讓別人在不運行在錯誤模式的狀況下可以正常的運行起來。。。。。。索引
上火。。事務
有想了解MYSQL 服務器mode的朋友能夠查看mysql5.1參考手冊 5.3.2 SQL服務器模式 一節。字符串
#############################華麗分割線###########################產品
#############################華麗分割線###########################
5.3.2. SQL服務器模式
MySQL服務器能夠以不一樣的SQL模式來操做,而且能夠爲不一樣客戶端應用不一樣模式。這樣每一個應用程序能夠根據本身的需求來定製服務器的操做模式。
模式定義MySQL應支持哪些SQL語法,以及應執行哪一種數據驗證檢查。這樣能夠更容易地在不一樣的環境中使用MySQL,並結合其它數據庫服務器使用MySQL。
你能夠用--sql-mode="modes"選項啓動mysqld來設置默認SQL模式。若是你想要重設,該值還能夠爲空(--sql-mode ="")。
你還能夠在啓動後用SET [SESSION|GLOBAL] sql_mode='modes'語句設置sql_mode變量來更改SQL模式。設置 GLOBAL變量時須要擁有SUPER權限,而且會影響從那時起鏈接的全部客戶端的操做。設置SESSION變量隻影響當前的客戶端。任何客戶端能夠隨時更改本身的會話 sql_mode值。
Modesis是用逗號(‘,’)間隔開的一系列不一樣的模式。你能夠用SELECT @@sql_mode語句查詢當前的模式。默認值是空(沒有設置任何模式)。
主要重要sql_mode值爲:
· ANSI
更改語法和行爲,使其更符合標準SQL。
· STRICT_TRANS_TABLES
若是不能將給定的值插入到事務表中,則放棄該語句。對於非事務表,若是值出如今單行語句或多行語句的第1行,則放棄該語句。本節後面給出了更詳細的描述。
· TRADITIONAL
Make MySQL的行爲象「傳統」SQL數據庫系統。該模式的簡單描述是當在列中插入不正確的值時「給出錯誤而不是警告」。註釋:一旦發現錯誤當即放棄INSERT/UPDATE。若是你使用非事務存儲引擎,這種方式不是你想要的,由於出現錯誤前進行的數據更改不會「滾動」,結果是更新「只進行了一部分」。
本手冊指「嚴格模式」,表示至少STRICT _TRANS_TABLES或STRICT _ALL_TABLES被啓用的模式。
下面描述了支持的全部模式:
· ALLOW_INVALID_DATES
在嚴格模式下不要檢查所有日期。只檢查1到12之間的月份和1到31之間的日。這在Web應用程序中,當你從三個不一樣的字段獲取年、月、日,而且想要確切保存用戶插入的內容(不進行日期驗證)時很重要。該模式適用於DATE和DATETIME列。不適合TIMESTAMP列,TIMESTAMP列須要驗證日期。
啓用嚴格模式後,服務器須要合法的月和日,不只僅是分別在1到12和1到31範圍內。例如,禁用嚴格模式時'2004-04-31'是合法的,但啓用嚴格模式後是非法的。要想在嚴格模式容許遮掩固定日期,還應啓用ALLOW_INVALID_DATES。
· ANSI_QUOTES
將‘"’視爲識別符引號(‘`’引號字符),不要視爲字符串的引號字符。在ANSI模式,你能夠仍然使用‘`’來引用識別符。啓用ANSI_QUOTES後,你不能用雙引號來引用字符串,由於它被解釋爲識別符。
· ERROR_FOR_DIVISION_BY_ZERO
在嚴格模式,在INSERT或UPDATE過程當中,若是被零除(或MOD(X,0)),則產生錯誤(不然爲警告)。若是未給出該模式,被零除時MySQL返回NULL。若是用到INSERT IGNORE或UPDATE IGNORE中,MySQL生成被零除警告,但操做結果爲NULL。
· HIGH_NOT_PRECEDENCE
NOT操做符的優先順序是表達式例如NOT a BETWEEN b AND c被解釋爲NOT (a BETWEEN b AND c)。在一些舊版本MySQL中, 表達式被解釋爲(NOT a) BETWEEN b AND c。啓用HIGH_NOT_PRECEDENCESQL模式,能夠得到之前的更高優先級的結果。
mysql> SET sql_mode = '';
mysql> SELECT NOT 1 BETWEEN -5 AND 5;
-> 0
mysql> SET sql_mode = 'broken_not';
mysql> SELECT NOT 1 BETWEEN -5 AND 5;
-> 1
· IGNORE_SPACE
容許函數名和‘(’之間有空格。強制將全部函數名視爲保存的字。結果是,若是你想要訪問保存爲字的數據庫、表或列名,你必須引用它。例如,由於有USER()函數,mysql數據庫中的user表名和該表內的User列被保存下來,所以你必須引用它們:
SELECT "User" FROM mysql."user";
· NO_AUTO_CREATE_USER
防止GRANT自動建立新用戶,除非還指定了密碼。
· NO_AUTO_VALUE_ON_ZERO
NO_AUTO_VALUE_ON_ZERO影響AUTO_INCREMENT列的處理。通常狀況,你能夠向該列插入NULL或0生成下一個序列號。NO_AUTO_VALUE_ON_ZERO禁用0,所以只有NULL能夠生成下一個序列號。
若是將0保存到表的AUTO_INCREMENT列,該模式會頗有用。(不推薦採用該慣例)。例如,若是你用mysqldump轉儲表並重載,MySQL遇到0值通常會生成新的序列號,生成的表的內容與轉儲的表不一樣。重載轉儲文件前啓用NO_AUTO_VALUE_ON_ZERO能夠解決該問題。mysqldump在輸出中自動包括啓用NO_AUTO_VALUE_ON_ZERO的語句。
· NO_BACKSLASH_ESCAPES
禁用反斜線字符(‘\’)作爲字符串內的退出字符。啓用該模式,反斜線則成爲普通字符。
· NO_DIR_IN_CREATE
建立表時,忽視全部INDEX DIRECTORY和DATA DIRECTORY指令。該選項對從複製服務器有用。
· NO_ENGINE_SUBSTITUTION
若是須要的存儲引擎被禁用或未編譯,能夠防止自動替換存儲引擎。
· NO_FIELD_OPTIONS
不要在SHOW CREATE TABLE的輸出中打印MySQL專用列選項。該模式在可移植模式(portability mode)下用於mysqldump。
· NO_KEY_OPTIONS
不要在SHOW CREATE TABLE的輸出中打印MySQL專用索引選項。該模式在可移植模式(portability mode)下用於mysqldump。
· NO_TABLE_OPTIONS
不要在SHOW CREATE TABLE的輸出中打印MySQL專用表選項(例如ENGINE)。該模式在可移植模式(portability mode)下用於mysqldump。
· NO_UNSIGNED_SUBTRACTION
在減運算中,若是某個操做數沒有符號,不要將結果標記爲UNSIGNED。請注意這樣使UNSIGNED BIGINT不能100%用於上下文中。參見12.8節,「Cast函數和操做符」。
· NO_ZERO_DATE
在嚴格模式,不要將 '0000-00-00'作爲合法日期。你仍然能夠用IGNORE選項插入零日期。在非嚴格模式,能夠接受該日期,但會生成警告。
· NO_ZERO_IN_DATE
在嚴格模式,不接受月或日部分爲0的日期。若是使用IGNORE選項,咱們爲相似的日期插入'0000-00-00'。在非嚴格模式,能夠接受該日期,但會生成警告。
· ONLY_FULL_GROUP_BY
不要讓GROUP BY部分中的查詢指向未選擇的列。
· PIPES_AS_CONCAT
將||視爲字符串鏈接操做符(+)(同CONCAT()),而不視爲OR。
· REAL_AS_FLOAT
將REAL視爲FLOAT的同義詞,而不是DOUBLE的同義詞。
· STRICT_TRANS_TABLES
爲全部存儲引擎啓用嚴格模式。非法數據值被拒絕。後面有詳細說明。
· STRICT_TRANS_TABLES
爲事務存儲引擎啓用嚴格模式,也可能爲非事務存儲引擎啓用嚴格模式。後面有詳細說明。
嚴格模式控制MySQL如何處理非法或丟失的輸入值。有幾種緣由可使一個值爲非法。例如,數據類型錯誤,不適合列,或超出範圍。當新插入的行不包含某列的沒有顯示定義DEFAULT子句的值,則該值被丟失。
對於事務表,當啓用STRICT_ALL_TABLES或STRICT_TRANS_TABLES模式時,若是語句中有非法或丟失值,則會出現錯誤。語句被放棄並滾動。
對於非事務表,若是插入或更新的第1行出現壞值,兩種模式的行爲相同。語句被放棄,表保持不變。若是語句插入或修改多行,而且壞值出如今第2或後面的行,結果取決於啓用了哪一個嚴格選項:
· 對於STRICT_ALL_TABLES,MySQL返回錯誤並忽視剩餘的行。可是,在這種狀況下,前面的行已經被插入或更新。這說明你能夠部分更新,這可能不是你想要的。要避免這點,最好使用單行語句,由於這樣能夠不更改表便可以放棄。
· 對於STRICT_TRANS_TABLES,MySQL將非法值轉換爲最接近該列的合法值並插入調整後的值。若是值丟失,MySQL在列中插入隱式 默認值。在任何狀況下,MySQL都會生成警告而不是給出錯誤並繼續執行語句。13.1.5節,「CREATE TABLE語法」描述了隱式默認值。
嚴格模式不容許非法日期,例如'2004-04-31'。它不容許禁止日期使用「零」部分,例如'2004-04-00'或「零」日期。要想禁止,應在嚴格模式基礎上,啓用NO_ZERO_IN_DATE和NO_ZERO_DATE SQL模式。
若是你不使用嚴格模式(即不啓用STRICT_TRANS_TABLES或STRICT_ALL_TABLES模式),對於非法或丟失的值,MySQL將插入調整後的值並給出警告。在嚴格模式,你能夠經過INSERT IGNORE或UPDATE IGNORE來實現。參見13.5.4.22節,「SHOW WARNINGS語法」。
下面的特殊模式快速組合了前面所列的模式。
其中包括大多數最新版本MySQL中的全部模式值。舊版本中,組合模式不包括新版本中沒有的不適用的具體模式值。
· ANSI
等同REAL_AS_FLOAT、PIPES_AS_CONCAT、ANSI_QUOTES、IGNORE_SPACE。參見1.8.3節,「在ANSI模式下運行MySQL」。
· DB2
等同PIPES_AS_CONCAT、ANSI_QUOTES、IGNORE_SPACE、NO_KEY_OPTIONS、NO_TABLE_OPTIONS、NO_FIELD_OPTIONS。
· MAXDB
等同PIPES_AS_CONCAT、ANSI_QUOTES、IGNORE_SPACE、NO_KEY_OPTIONS、NO_TABLE_OPTIONS、NO_FIELD_OPTIONS、 NO_AUTO_CREATE_USER。
· MSSQL
等同PIPES_AS_CONCAT、ANSI_QUOTES、IGNORE_SPACE、NO_KEY_OPTIONS、NO_TABLE_OPTIONS、 NO_FIELD_OPTIONS。
· MYSQL323
等同NO_FIELD_OPTIONS、HIGH_NOT_PRECEDENCE。
· MYSQL40
等同NO_FIELD_OPTIONS、HIGH_NOT_PRECEDENCE。
· ORACLE
等同PIPES_AS_CONCAT、ANSI_QUOTES、IGNORE_SPACE、NO_KEY_OPTIONS、NO_TABLE_OPTIONS、NO_FIELD_OPTIONS、NO_AUTO_CREATE_USER。
· POSTGRESQL
等同PIPES_AS_CONCAT、ANSI_QUOTES、IGNORE_SPACE、NO_KEY_OPTIONS、NO_TABLE_OPTIONS、NO_FIELD_OPTIONS。
· TRADITIONAL
等同STRICT_TRANS_TABLES、STRICT_ALL_TABLES、NO_ZERO_IN_DATE、NO_ZERO_DATE、ERROR_FOR_DIVISION_BY_ZERO、NO_AUTO_CREATE_USER。