MySQL第13天 S Q L M o d e 及 相 關 問 題 常用 S Q L 技 巧 和 常 見 問 題

MySQL中,SQL mode 常用來解決下面幾類問題


通過設置 SQL Mode,可以完成不同嚴格程度的數據校驗,有效地保障數據準確性。

通過設置 SQL Mode 爲 ANSI 模式,來保證大多數 SQL 符合標準的 SQL 語法,這樣應用在
不同數據庫之間進行遷移時,則不需要對業務 SQL 進行較大的修改。

在不同數據庫之間進行數據遷移之前,通過設置 SQL Mode 可以使 MySQL 上的數據更方
便地遷移到目標數據庫中。

1  設置模式爲嚴格模式


sql_mode 的 一 種 修 改 方 法 , 即 SET [SESSION|GLOBAL]sql_mode='modes',

其中 SESSION 選項表示只在本次連接中生效;而 GLOBAL 選項表示在本次不生效,而對於新的鏈接生效


SQL mode 的常見功能

(1)效驗日期數據合法性

ANSI模式:寬鬆模式



在 ANSI 模式下,非法日期可以插入,但是插入值卻變爲「0000-00-00 00:00:00」,
並且系統給出了 warning;而在 TRADITIONAL 模式下,在直接提示日期非法,拒絕插入


2   (2)在 INSERT 或 UPDATE 過程中,如果 SQL MODE 處於 TRADITIONAL 模式,
運行 MOD(X,0)會產生錯誤,因爲 TRADITIONAL 也屬於嚴格模式,在非嚴格模式下 MOD(X,0)返回的結
果是 NULL,所以在含有 MOD 的運算中要根據實際情況設定好 sql_mode。


3   (3)啓用 NO_BACKSLASH_ESCAPES 模式,使反斜線成爲普通字符。在導入數據時,如
果數據中含有反斜線字符,啓用 NO_BACKSLASH_ESCAPES 模式保證數據的正確性,是個不錯
的選擇

即將  NO_BACKSLASH_ESCAPES   添加,而不是隻選這個


(4)啓用 PIPES_AS_CONCAT 模式。將「||」視爲字符串連接操作符,在 Oracle 等數據
庫中,「||」被視爲字符串的連接操作符,所以,在其他數據庫中含有「||」操作符的 SQL
在 MySQL 中將無法執行,爲了解決這個問題,MySQL 提供了 PIPES_AS_CONCAT 模式。


常用的SQL Mode


SQL mode 在遷移中的使用
與其他異構數據庫之間有遷移需求,那麼SQL mode 可以有幫助


例如,在數據遷移過程中,可以設置 SQL Mode 爲 NO_TABLE_OPTIONS 模式,這樣將去掉 show
create table 中的「engine」關鍵字,獲得通用的建表腳本

小結

 SQL Mode 的「嚴格模式」爲 MySQL 提供了很好的數據校驗功能,保證了數據的準確性,
TRADITIONAL、STRICT_TRANS_TABLES 是常用的兩種嚴格模式。
 SQL Mode 的多種模式可以靈活組合,組合後的模式可以更好地滿足應用程序的需求。
尤其在數據遷移中,SQL Mode 的使用更爲重要


常 用 S Q L 技 巧 和 常 見 問 題


正則表達式的使用



MySQL 利用 REGEXP 命令提供給用戶擴展的正則表達式功能

1


2


3


4


5



使用RAND()提取隨機行

在MySQL中,產生隨機數的方法是RAND()
函數。可以利用這個函數與ORDER BY子句一起完成隨機抽取某些行的功能。它的原理其實
就是ORDER BY RAND()能夠把數據隨機排序

例如,隨機提取 sales2 中的5行數據

mysql> select * from sales2 order by rand() limit 5;


利用 GROUP BY 的 WITH ROLLUP 子句做統計


在SQL語句中,使用GROUP BY的WITH ROLLUP字句可以檢索出更多的分組聚合信息,它不僅
僅能像一般的GROUP BY語句那樣檢索出各組的聚合信息,還能檢索出本組類的整體聚合信


其實 WITH ROLLUP 反映的是一種 OLAP 思想,也就是說這一個 GROUP BY 語句執行完成後可
以滿足用戶想要得到的任何一個分組以及分組組合的聚合信息值。

注意: 1、當使用 ROLLUP 時, 不能同時使用 ORDER BY 子句進行結果排序。換言之, ROLLUP
和 ORDER BY 是互相排斥的
          2、LIMIT 用在 ROLLUP 後面。





用 BIT GROUP FUNCTIONS 做統計

主要介紹如何共同使用 GROUP BY 語句和 BIT_AND、BIT_OR 函數完成統計工作。
這兩個函數的一般用途就是做數值之間的邏輯位運算,但是,當把它們與 GROUP BY 子句聯
合使用的時候就可以做一些其他的任務。




一個超市需要記錄每個用戶每次來超市都購買了哪些商品

下面給出一種新的解決辦法,類似於上面講到的第二種方案,仍然用一個字段表示顧客購買
商品的信息,但是這個字段是數值型的而不是字符型的,該字段存儲一個十進制數字,當它
轉換成二進制的時候,那麼每一位代表一種商品,而且如果所在位是「1」那麼表示顧客購
買了該種商品,
「0」表示沒有購買該種商品。比如數值的第 1 位代表麪包(規定從右向左開
始計算)、第 2 位代表牛奶、第 3 位代表餅乾、第 4 位代表啤酒,這樣如果一個用戶購物單
的商品列的數值爲 5,那麼二進制表示爲 0101,這樣從右向左第 1 位和第 3 位是 1,那麼就
可以知道這個用戶購買了麪包和餅乾,而如果這個客戶有多個這樣的購物單(在數據庫中就
是有多條記錄),把這些購物單按用戶分組做 BIT_OR()操作就可以知道這個用戶都購買過什
麼商品。



其中 customerid 是顧客編號,kind 是所購買的商品,初始化了兩個顧客 1 和 2 的數據,他
們每人購物兩次,前者購買的商品數值是 5 和 4,轉化爲二進制分別爲 0101、0100,表示
這個顧客第一次購買了牛奶和啤酒,第二次購買了牛奶;後者購買的商品數值是 3 和 4,轉
化爲二進制分別爲 0011、0100,表示這個顧客第一次購買了餅乾和啤酒,第二次購買了牛
奶。
下面用 BIT_OR()函數與 GROUP BY 子句聯合起來,統計一下這兩個顧客在這個超市一共都購
買過什麼商品,如下例:






數據庫名、表名大小寫問題

在 MySQL 中如何在硬盤上保存、使用表名和數據庫名由 lower_case_tables_name 系統變量
決定,可以在啓動 mysqld 時設置這個系統變量。 lower_case_tables_name 可以採用如表 17-2
所示的任一值


儘管在某些平臺中數據庫名和表名對大小寫不敏感,但是最好養成在同一查詢中使用
相同的大小寫來引用給定的數據庫名或表名的習慣。


使用外建需要注意的問題

在 MySQL 中,InnoDB 存儲引擎支持對外部關鍵字約束條件的檢查。而對於其他類型存儲引
擎的表,當使用 REFERENCES tbl_name(col_name)子句定義列時可以使用外部關鍵字,但是
該子句沒有實際的效果,只作爲備忘錄或註釋來提醒用戶目前正定義的列指向另一個表中的
一個列。


用 show create table 命令查看建表語句的時候,發現 MyISAM 存儲引擎的並不顯示外
鍵的語句,而 InnoDB 存儲引擎的就顯示外鍵語句




小結


 應用正則表達式可以使用戶能夠在一段很大的字符串中找到符合自己規則的一些 語句,這個功能在進行匹配查找的時候非常有用。  RAND()函數與 ORDER BY 字句的配合使用能夠實現隨機抽取樣本的功能,這個技巧 在進行數據統計的時候很方便。  GROUP BY 的 WITH ROLLUP 字句能夠實現類似於 OLAP 的查詢。  BIT 函數與 GROUP BY 子句的聯合使用在某些應用場合可以大大降低存儲量,提高 統計查詢效率。  MySQL 數據庫名和表名的大小寫與操作系統對大小寫的敏感性關係密切,因此需 要格外引起用戶的注意。  MySQL 的外鍵功能僅對 InnoDB 存儲引擎的表有作用,其他類型存儲引擎的表雖然 可以建立外鍵,但是並不能起到外鍵的作用。