《Mysql必知必會》讀書筆記
《Mysql必知必會》(MySQL Crash Course)內容很豐富,mysql的各個方面都涉及到了,從基本的SQL增刪改查到觸發器、事務以及安全管理和效能提升,本書都做了精簡的介紹。
相比於另外兩本相關的初學者讀物——《SQL基礎教程》MICK著和《MySQL與MariaDB學習指南》。這本書可能更適合想對mysql有全面瞭解的(比如對mysql的高階功能)或者想成為資料庫管理員的人閱讀。
簡要介紹
Ref: http://dev.mysql.com/
- 本書的配套網站MySQL Crash Course,原作者很厲害,畢竟他之前就出了一本堪稱全世界用得最多的一本SQL教程--
Sams Teach Yourself SQL in 10 Minutes
( 中文版《SQL必知必會》,人民郵電出版社出版) - 資料庫(database) 是儲存有組織的資料的容器(通常是一個文 件或一組檔案,而資料庫軟體應稱為DBMS(資料庫管理系統)
- 模式(
schema
) && 資料庫(database
)? —— 一般情況下,模式用作資料庫的同義詞,模式(schema) 關於資料庫和表的佈局及特性的資訊 - 記錄(
record
) && 行(row
)?—— 在很大程度上,這兩個術語是可以互相 替代的,但從技術上說,行才是正確的術語 - SQL(發音為字母S-Q-L或sequel)是結構化查詢語言(Structured Query Language)的縮寫。
- DBMS可分為兩類:
一類為基於共享檔案系統的DBMS
,另一類為基於客戶機—伺服器的DBMS。
- 前者如Microsoft Access和FileMaker等,用於桌面用途,通常不用於高階或更關鍵的應用
- 後者如MySQL、Oracle以及Microsoft SQL Server等資料庫是基於客戶機—服 務器的資料庫。
- 寫SQL語句的慣例——關鍵詞都大寫,表明列名小寫
基本用法
- 多用SHOW,
HELP SHOW
,SHOW GRANTS
,SHOW ERRORS
,SHOW WARNINGS
DESCRIBE customers;
是SHOW COLUMNS FROM customers;
的快捷方式INFORMATION_SCHEMA
- 在處理SQL語句時,其中所有空格都被忽略。
- 查詢結果預設是升序排序(從A到Z)
!=
等同於<>
操作符- SQL(像多數語言一樣)在處理OR操作符前,優先處理AND操作符!!!
- 最好使用圓括號明確地分組相應的操作符
WHERE id=1002 OR id=1003 AND price>=10
這個WHERE字句的計算次序呢?
- MySQL支援使用NOT對
IN
、BETWEEN
和EXISTS
子句取反,這與多數其他DBMS允許使用NOT對各種條件 取反有很大的差別。 - 從技術上說,LIKE是謂詞而不是操作符。
- 雖然似乎%萬用字元可以匹配任何東西,但有一個例外,即NULL。 即使是
WHERE prod_name LIKE '%'
也不能匹配用值NULL作為產品名的行 - MySQL正規表示式
- 用
REGEXP
代替LIKE
- 為了匹配特殊字元,必須用
\\
為前導。\\-
表示查詢-,\\.
表示查詢.
。如WHERE name REGEXP '\\.'
\
&&\\
? 多數正規表示式實現使用單個反斜槓轉義特殊字元, 以便能使用這些字元本身。但MySQL要求兩個反斜槓(MySQL 自己解釋一個,正規表示式庫解釋另一個)。- 常用的字元類(character class), 如
[:alnum:]
匹配任意字母和數字(同[a-zA-Z0-9]),[:alpha:]
匹配任意字元(同[a-zA-Z]) - 定位元字元:
[[:<:]]
和[[:>:]]
分別匹配詞的開始和結尾
- 用
- LIKE和REGEXP 的不同在於,LIKE匹配整個串而REGEXP匹配子串。利用定位 符,通過用
^
開始每個表示式,用$
結束每個表示式,可以使 REGEXP的作用與LIKE一樣。 - 多數DBMS使用
+或||
來實現拼接, MySQL則使用Concat()
函式來實現 SUM(), MIN(), MAX()
會忽略列值為NULL的行。COUNT()
函式有兩種使用方式。
- 使用
COUNT(*)
對錶中行的數目進行計數,不管表列中包含的是空 值(NULL)還是非空值。 - 使用
COUNT(column)
對特定列中具有值的行進行計數,忽略NULL值,如果指定列名,則DISTINCT只能用於COUNT()
。DISTINCT 不能用於COUNT(*)
,因此不允許使用COUNT(DISTINCT)
, 否則會產生錯誤。類似地,DISTINCT
必須使用列名,不能用於計算或表示式。
- 使用
- 分組
- 如果分組列中具有NULL值,則NULL將作為一個分組返回。如果列 中有多行NULL值,它們將分為一組。
- 使用
WITHROLLUP
關鍵字,可以得到每個分組以 及每個分組彙總級別(針對每個分組)的值,GROUP BY id WITH ROLLUP
- WHERE在資料 分組前進行過濾,HAVING在資料分組後進行過濾
- ANSI SQL規範首選INNER JOIN語法。此外, 儘管使用WHERE子句定義聯結的確比較簡單,但是使用明確的 聯結語法能夠確保不會忘記聯結條件,有時候這樣做也能影響 效能。
- UNION中的每個查詢必須包含相同的列、表示式或聚集函式(不過各個列不需要以相同的次序列出)。
- 在INSERT和INTO之間新增關鍵字
LOW_PRIORITY
,指示MySQL 降低INSERT語句的優先順序,INSERT LOW_PRIORITY INTO
- 如果用UPDATE語句更新多行,並且在更新這些行中的一行或多行時出一個現錯誤,則整個UPDATE操作被取消 (錯誤發生前更新的所有行被恢復到它們原來的值)。為即使是發
生錯誤,也繼續進行更新,可使用IGNORE關鍵字,UPDATE IGNORE customers...
- 如果僅想在一個表不存在時建立它,應該在表名後給出
IF NOT EXISTS
last_insert_id()
函式可以獲取AUTO_INCREMENT
對應的值- 需要知道的引擎
InnoDB
是一個可靠的事務處理引擎,它不支援全文字搜尋;MEMORY
在功能等同於MyISAM,但由於資料儲存在記憶體(不是磁碟)中,速度很快(特別適合於臨時表);MyISAM
是一個效能極高的引擎,它支援全文字搜尋, 但不支援事務處理。
RENAME TABKE xx TO yy;
CREATE OR REPLACE VIEW xxx
, 檢視可以巢狀,但不能索引,也不能有關聯的觸發器
高階用法
1. 全文字搜尋
- 兩個最常使用的引擎為MyISAM和InnoDB, 前者支援全文字搜尋,而後者不支援
- 全文字搜尋在效能、明確控制和智慧化的結果(例如,一個特殊詞的搜尋將會返回包含該詞的所有行,而不區分 包含單個匹配的行和包含多個匹配的行)方面很有優勢
- 為了進行全文字搜尋,必須索引被搜尋的列,而且要隨著資料的改 變不斷地重新索引,
FULLTEXT(note_text)
的表示對note_text
進行索引 - 使用兩個函式
Match()
和Against()
執行全文字搜尋, 其中Match()
指定被搜尋的列,Against()
指定要使用的搜尋表示式 - 除非使用
BINARY
方式, 否則全文字搜尋不區分大小寫。 - 全文字搜尋的一 個重要部分就是對結果排序。具有較高等級的行先返回(因為這些行很 可能是你真正想要的行)。
- Match()和Against() 用來建立一個計算列(別名為rank),此列包含全文字搜尋計算出的等級值。
- 文字中詞靠前的行的等級值比詞靠後的 行的等級值高。
- 查詢擴充套件——利用查詢擴充套件,能找出可能相關的結果,即使它們並不精確包含所 查詢的詞。
WHERE Match(note_text) Against('anvils' WITH QUERY EXPANSION)
WHERE Match(note_text) Against('anvils')
- 布林文字搜尋
- 即使沒有FULLTEXT索引也可以使用, 但這是一種非常緩慢的操作
WHERE Match(note_text) Against('heavy' IN BOLLEAN MODE)
WHERE Match(note_text) Against('heavy -rope*' IN BOLLEAN MODE)
匹配包含heavy但不包含任意以rope開始的詞的行- 全文字布林操作符
-
排除一個詞,而*
是截斷操作符(可想象為用於詞尾的一個萬用字元) - 在布林方式中,不按等級值降序排序返回的行。
- 在索引全文字資料時,短詞被忽略且從索引中排除。短詞定義為 那些具有3個或3個以下字元的詞(如果需要,這個數目可以更改)
- MySQL帶有一個內建的非用詞(
stopword
)列表,這些詞在索引全文字資料時總是被忽略。 - MySQL規定了一條50%規則,如果一個詞出現在50%以上 的行中,則將它作為一個非用詞忽略。50%規則不用於IN BOOLEAN MODE。
- 忽略詞中的單引號。例如,don't索引為dont。
2. 儲存過程
- 儲存過程簡單來說,就是為以後的使用而儲存 的一條或多條MySQL語句的集合
- MySQL稱儲存過程的執行為呼叫,因此MySQL執行儲存過程的語句為
CALL
。 - mysql命令列客戶機的分隔符
- 預設的MySQL語句分隔符為;
DELIMITER //
告訴命令列實用程式使用//
作為新的語句結束分隔符- 除
\
符號外,任何字元都可以用作語句分隔符
SHOW PROCEDURE STATUS
,SHOW PROCEDURE STATUS LIKE 'xxx'
,SHOW CREATE PROCEDURE xxx
- 所有MySQL變數都必須以
@
開始,set total=1; select @total;
- MySQL支援IN(傳遞給儲存過程)、OUT(從存 儲過程傳出,如這裡所用)和INOUT(對儲存過程傳入和傳出)型別的參 數。
- 簡單範例,呼叫儲存過程則鍵入
call productpricing;
即可
mysql
DELIMITER //
CREATE PROCEDURE productpricing() COMMENT 'xxxx'
BEGIN
SELECT Avg(xx) AS yy INTO zz
FROM aa;
-- comment
DECLAR total DECIMAL(8,2);
IF taxable THEN
SELECT xx INTO yy;
END IF;
END //
DELIMITER ;
3. 遊標
- 遊標(cursor)是一個儲存在MySQL伺服器上的資料庫查詢, 它不是一條SELECT語句,而是被該語句檢索出來的結果集。
- SELECT -- MySQL檢索操作返回一組稱為結果集的行
- 不像多數DBMS,MySQL遊標只能用於儲存過程(和函式)。
- 使用遊標
- 宣告(定義)--> 開啟使用 --> 取出資料 --> 關閉
- 如果你不明確關閉遊標,MySQL將會在到達END語 句時自動關閉它
- DECLARE語句的釋出存在特定的次序。 用DECLARE語句定義的區域性變數必須在定義任意遊標或控制程式碼 之前定義,而控制程式碼必須在遊標之後定義。不遵守此順序將產 生錯誤訊息。
- 通常REPEAT語句的語法使它更適合於對遊標進行迴圈
DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET done=1;
- 這條語句定義了一個CONTINUE HANDLER,它是在條件出現時被執行的程式碼。
- 這裡,它指出當SQLSTATE '02000'出現時,
SET done=1
。SQLSTATE '02000'
是一個未找到條件,當REPEAT由於沒有更多的行供迴圈而不能繼 續時,出現這個條件。
- 簡單例子
CREATE PROCEDURE processorders()
BEGIN
-- Declare local variable
DECLARE done BOOLEAN DEFAULT 0;
DECLARE o INT;
DECLARE t DECIMAL(8,2);
-- Declare the cursor
DECLARE ordernumbers CURSOR FOR SELECT order_num FROM ordres;
DECLARE CONINTUE HANDLER FOR SQLSTATE '02000' SET done=1;
-- Create a table to store the results
CREATE TABLE IF NOT EXISTS ordertotals
(order_num int, total decimal(8,2))
-- Open the cursor
OPEN ordernumbers;
-- Loop through all rows
REPEAT
-- get order number
FETCH ordernumbers INTO o;
-- get the total for the order
CALL ordertotal(o, 1, t);
-- Insert order and total into ordertotals
INSERT INTO ordertotals(order_num, total) VALUES(o, t);
-- End of loop
UNTIL DONE END REPEAT;
-- Close the cursor
CLOSE ordernumbers;
END;
4. 觸發器
- 觸發器是MySQL響應以下任意語句而 自動執行的一條MySQL語句(或位於BEGIN和END語句之間的一組語句):
- DELETE
- INSERT
- UPDATE
- 每個表最多支援6個觸發器(每條INSERT、UPDATE 和DELETE的之前和之後)。
- 觸發器名必 須在每個表中唯一,但不是在每個資料庫中唯一。
DROP TRIGGER
CREATE TRIGGER newproduct AFTER INSERT ON products FOR EACH ROW SELECT 'Product added'
FOR EACH ROW
對每個插入執行
- 只有表才支援觸發器,檢視不支援(臨時表也不 支援)。
- INSERT
- 在INSERT觸發器程式碼內,可引用一個名為NEW的虛擬表,訪問被 插入的行;
- 對於AUTO_INCREMENT列,NEW在INSERT執行之前包含0, 在INSERT 執行之後包含新的自動生成值。
CREATE TRIGGER neworder AFTER INSERT ON orders FOR EACH ROW SELECT NEW.order_num;
- DELETE
- 在DELETE觸發器程式碼內,你可以引用一個名為OLD的虛擬表,訪 問被刪除的行
- OLD中的值全都是隻讀的,不能更新
- UPDATE
- 在UPDATE觸發器程式碼中,你可以引用一個名為OLD的虛擬表訪問 以前(UPDATE語句前)的值,引用一個名為NEW的虛擬表訪問新 更新的值;
CREATE TRIGGER updatevendeor BEFORE UPDATE ON vendors FOR EACH ROW SET NEW.vend_state=Upper(New.ven_state);
- 進一步介紹
- MySQL觸發器中不支援CALL語句。這表示不能從觸發 器內呼叫儲存過程。所需的儲存過程程式碼需要複製到觸發器內。
- 使用觸發器, 把更改(如果需要,甚至還有之前和之後的狀態)記錄到另一個 表非常容易。
- 應該用觸發器來保證資料的一致性(大小寫、格式等)。
- 簡單舉例
sql
CREATE TRIGGER deleteorder BEFORE DELETE ON orders
FOR EACH ROW
BEGIN
INSERT INTO archive_orders(order_num, order_date, cust_id)
values(OLD.order_num, OLD.order-date, OLD.cust_id);
END;
5. 事務處理
- 事務處理(transaction processing)可以用來維護資料庫的完整性,它 保證成批的MySQL操作要麼完全執行,要麼完全不執行。
- 術語
- 事務(transaction)指一組SQL語句;
- 回退(rollback)指撤銷指定SQL語句的過程;
- 提交(commit)指將未儲存的SQL語句結果寫入資料庫表;
- 保留點(savepoint)指事務處理中設定的臨時佔位符(placeholder),你可以對它釋出回退(與回退整個事務處理不同)。
- 不能回退CREATE或DROP操作。事務處理塊中可以使用這兩條語句,但如果你執行回退,它們不會被撤銷。
- 一般的Mysql語句是隱含提交(implicit commit),即提交(寫或儲存)操作是自動進行的。
START TRANSACTION;
DELETE FROM orderitems WHERE order_num=20120;
DELETE FROM orders WHERE order_num=2001;
COMMIT; SAVEPOINT delete1;
,ROLLBACK TO delete1;
- 保留點在事務處理完成(執行一條ROLLBACK或 COMMIT)後自動釋放
RELEASE SAVEPOINT
可以明確地釋放保留點。
autocommit
標誌決定是否自動提交更改,SET autocommit=0
--> 指示Mysql不自動提交- autocommit標誌是針對每個連線而不是服 務器的。
深入瞭解
- 字元和校對
字符集
為字母和符號的集合;編碼
為某個字符集成員的內部表示;校對
為規定字元如何比較的指令。
SHOW CHARACTER SET;
,SHOW COLLATION;
SHOW VARIABLES LIKE 'character%';
SHOW VARIABLES LIKE 'collation%';
- 使用
Cast()
或Convert()
函式,可在字符集之間進行轉化 SHOW GRANTS FOR yourname;
SET PASSWORD=Password('hello');
- 為了保證所有資料被寫到磁碟(包括索引 資料),可能需要在進行備份前使用
FLUSH TABLES
語句。 - 資料庫維護
ANALYZE TABLE tblname;
用來檢查表鍵是否正確CHECK TABLE tblname1, tblname2;
可選CHANGED
,EXTENED
,FAST
,MEDIUM
,QUICK
- CHECK TABLE支援一系列的用於MyISAM表的方式
- CHANGED 檢查自最後一次檢查以來改動過的表
- EXTENDED 執行最徹底的檢查
- FAST 只檢查未正常關閉的表
- MEDIUM 檢查所有被刪 除的連結並進行鍵檢驗
- QUICK 只進行快速掃描
REPAIR TABLE tblname3;
這條語句不應該經常使用,如果 需要經常使用,可能會有更大的問題要解決OPTIMIZE TABLE tblname4;
可用來在刪除大量資料後回收所用空間
- mysqld 的
--safe-mode
裝載減去某些最佳配置的伺服器 - MySQL的主要日誌檔案:錯誤日誌、查詢日誌、二進位制日誌、緩慢查詢日誌
SHOW PROCESSLIST
可以顯示所有活動的程式(以及它們的執行緒ID和執行時間)。- 使用EXPLAIN語句讓MySQL解釋它將如何執行一條SELECT語句
- 有的操作(包括INSERT)支援一個可選的DELAYED關鍵字,如果使用它,將把控制立即返回給呼叫程式,並且一旦有可能就實際 執行該操
- LIKE很慢,一般來說,最好是使用FULLTEXT而不是LIKE。
相關文章
- mysql必知必會筆記MySql筆記
- MySQL必知必會筆記——查詢的基礎知識MySql筆記
- SQL必知必會筆記(上)SQL筆記
- SQL必知必會筆記(下)SQL筆記
- MySQL 必知必會MySql
- 【必知必會的MySQL知識】①初探MySQLMySql
- 【必知必會的MySQL知識】②使用MySQLMySql
- Mysql必知必會練習MySql
- 01-mysql必知必會MySql
- MySQL必知必會 學習筆記 第十四章 使用子查詢MySql筆記
- MYSQL中的鎖必知必會MySql
- 【必知必會的MySQL知識】④DCL語言MySql
- 【必知必會的MySQL知識】⑤DQL語言MySql
- 【必知必會的MySQL知識】③DML語言MySql
- 《MySQL必知必會》萬用字元 ( like , % , _ ,)MySql字元
- MySQL必知必會》正規表示式MySql
- MySQL必知必會(1-12章)MySql
- MySQL必知必會詳細總結MySql
- 【必知必會的MySQL知識】mysql5.7安裝教程MySql
- 《MySQL 必知必會》C25-C28MySql
- Linux必會必知Linux
- git必會必知Git
- Redis 必知必會Redis
- ThreadLocal必知必會thread
- Activity 必知必會
- JSON 必知必會JSON
- HashMap必知必會HashMap
- 12.MySQL必知必會之分組資料MySql
- 《正規表示式必知必會》學習筆記以及示例文件筆記
- notion database 必知必會Database
- Linux shell必知必會Linux
- Linux 程式必知必會Linux
- 必知必會Java命令-jpsJava
- Redis 必知必會之 APIRedisAPI
- HTTP 必知必會的那些HTTP
- 常用技術必知必會
- MySQL 必知概念MySql
- using 你知道多少?你必須知道的.NET讀書筆記筆記