mysql 嚴格模式
mysql的sql_mode合理設定
sql_mode是個很容易被忽視的變數,預設值是空值,在這種設定下是可以允許一些非法操作的,比如允許一些非法資料的插入。
在生產環境必須將這個值設定為嚴格模式,所以開發、測試環境的資料庫也必須要設定,這樣在開發測試階段就可以發現問題.
sql model 常用來解決下面幾類問題
1 通過設定sql mode, 可以完成不同嚴格程度的資料校驗,有效地保障資料準備性。
2 通過設定sql model 為寬鬆模式,來保證大多數sql符合標準的sql語法,這樣應用在不同資料庫之間進行遷移時,
則不需要對業務sql 進行較大的修改。
3 在不同資料庫之間進行資料遷移之前,通過設定sql mode 可以使mysql 上的資料更方便地遷移到目標資料庫中。
sql_mode常用值
only_full_group_by
對於group by聚合操作,如果在select中的列,沒有在group by**現,那麼這個sql是不合法的,因為列不在group by從句中.
no_auto_value_on_zero
該值影響自增長列的插入。預設設定下,插入0或null代表生成下乙個自增長值。如果使用者 希望插入的值為0,而該列又是自增長的,那麼這個選項就有用了.
strict_trans_tables
在該模式下,如果乙個值不能插入到乙個事務表中,則中斷當前的操作,對非事務表不做限制.
no_zero_in_date
在嚴格模式下,不允許日期和月份為零
no_zero_date
設定該值,mysql資料庫不允許插入零日期,插入零日期會丟擲錯誤而不是警告
error_for_division_by_zero
在insert或update過程中,如果資料被零除,則產生錯誤而非警告。如 果未給出該模式,那麼資料被零除時mysql返回null
no_auto_create_user
禁止grant建立密碼為空的使用者
no_engine_substitution
如果需要的儲存引擎被禁用或未編譯,那麼丟擲錯誤。不設定此值時,用預設的儲存引擎替代,並丟擲乙個異常
pipes_as_concat
將"||"視為字串的連線操作符而非或運算子,這和oracle資料庫是一樣的,也和字串的拼接函式concat相類似
ansi_quotes
啟用ansi_quotes後,不能用雙引號來引用字串,因為它被解釋為識別符
oracle的sql_mode設定
oracle的sql_mode設定等同:pipes_as_concat, ansi_quotes, ignore_space, no_key_options,
no_table_options, no_field_options, no_auto_create_user.
如果使用mysql,為了繼續保留大家使用oracle的習慣,可以對mysql的sql_mode設定如下
在my.cnf新增如下配置
[mysqld]
sql_mode='only_full_group_by,no_auto_value_on_zero,strict_trans_tables,no_zero_in_date,
no_zero_date,error_for_division_by_zero,no_auto_create_user,pipes_as_concat,ansi_quotes'
注意mysql5.6和mysql5.7預設的sql_mode模式引數是不一樣的,5.6的mode是no_engine_substitution,
其實表示的是乙個空值,相當於沒有什麼模式設定,可以理解為寬鬆模式。5.7的mode是strict_trans_tables,也就是嚴格模式。
如果設定的是寬鬆模式,那麼我們在插入資料的時候,即便是給了乙個錯誤的資料,也可能會被接受,並且不報錯,
例如:我在建立乙個表時,該表中有乙個欄位為name,給name設定的字段型別時char(10),如果我在插入資料的時候,
其中name這個字段對應的有一條資料的長度超過了10,例如'1234567890abc',超過了設定的字段長度10,那麼不會報錯,
並且取前十個字元存上,也就是說你這個資料被存為了'1234567890',而'abc'就沒有了,但是我們知道,我們給的這條資料是錯誤的,
因為超過了字段長度,但是並沒有報錯,並且mysql自行處理並接受了,這就是寬鬆模式的效果,其實在開發、測試、生產等環境中,
我們應該採用的是嚴格模式,出現這種錯誤,應該報錯才對,所以mysql5.7版本就將sql_mode預設值改為了嚴格模式,
並且我們即便是用的mysql5.6,也應該自行將其改為嚴格模式,而你記著,mysql等等的這些資料庫,
都是想把關於資料的所有操作都自己包攬下來,包括資料的校驗,其實好多時候,我們應該在自己開發的專案程式級別將這些校驗給做了,
雖然寫專案的時候麻煩了一些步驟,但是這樣做之後,我們在進行資料庫遷移或者在專案的遷移時,就會方便很多,這個看你們自行來衡量。
mysql除了資料校驗之外,你慢慢的學習過程中會發現,它能夠做的事情還有很多很多,將你程式中做的好多事情都包攬了。
改為嚴格模式後可能會存在的問題
若設定模式中包含了no_zero_date,那麼mysql資料庫不允許插入零日期,插入零日期會丟擲錯誤而不是警告。
例如表中含欄位timestamp列(如果未宣告為null或顯示default子句)將自動分配default '0000-00-00 00:00:00'(零時間戳),
也或者是本測試的表day列缺省允許插入零日期 '0000-00-00' comment '日期';這些顯然是不滿足sql_mode中的no_zero_date而報錯。
模式設定和修改(以解決上述問題為例)
方式一:先執行select @@sql_mode,複製查詢出來的值並將其中的no_zero_in_date,no_zero_date刪除,
然後執行set sql_mode = '修改後的值'或者set session sql_mode='修改後的值';,例如:set session sql_mode='strict_trans_tables';
改為嚴格模式此方法只在當前會話中生效,關閉當前會話就不生效了。
方式二:先執行select @@global.sql_mode,複製查詢出來的值並將其中的no_zero_in_date,no_zero_date刪除,
然後執行set global sql_mode = '修改後的值'。此方法在當前服務中生效,重新mysql服務後失效
方法三:在mysql的安裝目錄下,或my.cnf檔案(windows系統是my.ini檔案),新增 sql_mode = only_full_group_by,
strict_trans_tables,error_for_division_by_zero,no_auto_create_user,no_engine_substitution,
新增my.cnf如下:
[mysqld]
sql_mode=only_full_group_by,strict_trans_tables,error_for_division_by_zero,no_auto_create_user
然後重啟mysql。
此方法永久生效.當然生產環境上是禁止重啟mysql服務的,所以採用方式二加方式三來解決線上的問題,那麼即便是有一天真的重啟了mysql服務,也會永久生效了。
作 者:郭楷豐
自 勉:生活,需要追求;夢想,需要堅持;生命,需要珍惜;但人生的路上,更需要堅強。帶著感恩的心啟程,學會愛,愛父母,愛自己,愛朋友,愛他人。
MySQL 嚴格模式與非嚴格模式
檢視 mysql 是否是嚴格模式 select sql mode 如果顯示包含 strict trans tables 或 strict all tables,則代表 mysql 開啟了嚴格模式 反之,是非嚴格模式 非嚴格模式是乙個相對概念 對於 innodb 引擎來說,strict trans t...
MySQL的嚴格模式設定
我們剛剛在上面設定了char,tinyint,儲存資料時超過它們的最大儲存長度,發現資料也能正常儲存進去,只是mysql幫我們自動擷取了最大長度。但在實際情況下,我們應該儘量減少資料庫的操作,緩解資料庫的壓力,讓它僅僅只管理資料即可,這樣的情況下就需要設定嚴格模式 show variables li...
關於mysql啟用嚴格模式問題
這是資料表的資料 密碼 pwsw 在mysql5.7 select from select from vinston unit practice where u id 12 and status 1 and first id 205 and update time is not null order...