說明:如下內容是閱讀書籍<<MySQL必知必會>>的摘要和總結mysql
模式能夠用來描述數據庫中特定的表以及整個數據庫,和其中表的關係
行(row) 表中的一個記錄正則表達式
必須先使用use命令打開數據庫,才能讀取其中的數據。sql
mysql> show columns from user;//DESCRIBE help show; > select distinct prod_id prod_name,prod_price from products;//返回不一樣的行!DISTINCT,限制返回結果。LIMIT SELECT prod_name,FROM products LIMIT 3,3(start,rows)
若是使用DISTINCT關鍵字,它必須直接放在全部列的前面,徹底限定符:表名.列名
子句(clause) SQL語句由子句構成,有些子句是必需的,而有的是可選的。數據庫
SELECT DISTINCT FOROM prod_name FROM products ORDER BY prod_name LIMIT 2,4;
結構體排序。先,,而後。。指定多列,用逗號隔開,DESC關鍵字只應用到直接位於其前面的列名,多列降序排列,則每一個列都須要指定DESC關鍵字。安全
單引號用來限定字符串。若是將值與串類型的列進行比較,則須要限定引號。用來與數值列進行比較的值不用引號。範圍運算符between服務器
SELECT prod_name,prod_price FROM prodects WHERE prod_price BETWEEN 4 AND 5; SELECT prod_id ,prod_prices FROM produts WHERE prod_id=1002 AND prod_price<=10; SELECT prod_id ,prod_prices FROM produts WHERE prod_id NOT IN(1002,1004)AND prod_price<=10; SELECT prod_name FROM prodects WHERE prod_name LIKE jar%; SELECT prod_name FROM prodects WHERE prod_name LIKE j_r%; //WHERE prod_price is null
MySQL容許給出多個WHERE子句。這些子句能夠兩種方式使用:以AND子句的方式或OR子句的方式使用,AND在計算次序中優先級更高,使用括號改變優先級,OR的泛化-- -- IN
IN的最大優勢是能夠包含其餘SELECT語句,使得可以更動態地創建WHERE子句
WHERE子句中的NOT操做符有且只有一個功能,那就是否認它以後所跟的任何條件。ide
爲在搜索子句中使用通配符,必須使用LIKE操做符,%表示任何字符出現任意次數
,下劃線只匹配單個字符
,通配符不要放在開始。正則表達式函數
SELECT prod_name FROM products WHERE prod_name REGEXP '1000' ORDER BY prod_name ;//替代了LIKE
LIKE匹配整個列,而REGEXP在列值內進行匹配。使用^(開始)和$(結束)定位符(anchor)便可,爲了匹配特殊字符,必須用\ \爲前導。性能
區分通配符和正則表達式(匹配範圍、匹配幾個字符之一,或者)測試
可使用預約義的字符集,稱爲字符類(character class)
存儲在表中的數據都不是應用程序所須要的。須要轉換-- -計算字段,例如,拼接。沒有列名,須要用AS來指定。計算字段的另外一常見用途是對檢索出的數據進行算術計算.
SELECT Concat(RTrim(vend_name),' (',vend_country,')') AS vend_title FROM vendors ORDER BY vend_name; SELECT 2*4 XXX;//算術運算符
日期和時間函數在MySQL語言中具備重要的做用。
DateDiff() 計算兩個日期之差
不管你何時指定一個日期,無論是插入或更新表值仍是用WHERE子句進行過濾,日期必須爲
格式yyyy-mm-dd。
datatime與date類型比較,截取相同部分比較Date(xxx)
針對對象,列:avg,max(單列、忽略null),min ,sum,count()返回某列的行數
AVG()只用於單個列
COUNT()函數進行計數。可利用COUNT()肯定表中行的數目或符合特定條件的行的數目
SELECT SUM(item*quantity) AS total_price FROM orderitems WHERE order_num=23000; SELECT AVG(DISTINCT prod_price) AS avg_price FROM products WHERE vend_id=2003; SELECT COUNT(*) AS num_items, MIN(prod_price) AS price_min, MAX(prod_price) AS price_max, AVG(prod_price) AS price_avg, FROM products 這些函數是高效設計的
分組容許把數據分爲多個邏輯組,以便能對每一個組進行彙集計算。
彙集對象默認是表
SELECT vend_id,COUNT(*) AS num_prods FROM products GROUP BY vend_id.//按照商家分組
這致使對每一個vend_id,而不是整個表計算num_prods一次
GROUP BY子句中列出的每一個列都必須是檢索列或有效的表達式(但不能是彙集函數)。若是在SELECT中使用表達式,則必須在GROUP BY子句中指定相同的表達式。不能使用別名。除彙集計算語句外,SELECT語句中的每一個列都必須在GROUP BY子句中給.
where-- >groub by -- >order by desc limit
目前爲止所學過的全部類型的WHERE子句均可以用HAVING來替代。惟一的差異是WHERE過濾行,而HAVING過濾分組。HAVING支持全部WHERE操做符。語義相同,但針對對象不一樣。這裏有另外一種理解方法,WHERE在數據分組前進行過濾,HAVING在數據分組後進行過濾。
SELECT cust_id,COUNT(*) AS orders FROM orders GROUP BY cust_id HAVING COUNT(*)>2; //它保留COUNT(*) >=2(兩個以上的訂單)的那些分組
同時使用where和group by
SELECT vend_id,COUNT(*) AS num_prods FROM products WHERE prod_price >=10;//對所的行過濾,無論你是哪一個組!體會,where是分組前的操做 GROUP BY vend_id HAVING COUNT(*) >=3;
ORDER BY | GROUP BY |
---|---|
排序產生的輸出 | 分組行。但輸出可能不是分組的順序 |
任意列均可以使用(甚至 非選擇的列也可使用) |
只可能使用選擇列或表達式列,SELECT中出現的,並且必須使用每一個選擇列表達式 |
不必定須要 | 若是與彙集函數一塊兒使用列(或表達式),則必須使用, |
千萬不要僅依賴GROUP BY排序數據。SELE
SELECT order_num ,SUM(quantity*item_prices) AS order_total FROM orderitems GROUP BY order_num//須要和select中的列相同,除了彙集函數 HAVING SUM(quantity*item_price)>=50 ORDER BY order_total;
利用子查詢進行過濾,select的結果可用於另外一條SELECT語句的WHERE子句。內層的SELECT語句的列和外層的WHERE列相同
SELECT order_num FROM orderitems WHERE prod_id='INIT2';//20002,20004 SELECT cust_id FROM orders WHERE order_num IN(20002,20004) 合併 SELECT cust_id FROM orders WHERE order_num IN(SELECT order_num FROM orderitems WHERE prod_id='INT2');//執行流程:從內向外。 //查詢ID的信息。 SELECT cust_name,cust_contact FROM customers WHERE cust_id IN(SELECT cust_id//返回客戶ID FROM orders WHERE order_num IN(SELECT order_num//返回訂單號列表 FROM orderitems WHERE prod_id='INT2'));
做爲計算字段使用子查詢,子查詢:過濾或者使用計算字段
--每一個客戶的總訂單數 思路:先求單個客戶的,而後使用子查詢 SELECT COUNT(*) AS orders FROM orders WHERE cust_id=10001; //爲了對每一個能夠執行COUNT(*) ,子查詢 SELECT cust_name, cust_state, (SELECT COUNT(*) FROM orders WHERE orders.cust_id=customers.cust_id) AS orders FROM customers ORDER BY cust_name;
測試時外層循環用硬編碼,eg:where cust_id=23223;
子查詢最多見的使用是在WHERE子句的IN操做符中,以及用來填充計算列
一類數據一個表。各表經過某些經常使用的值(即關係設計中的關係(relational))互相關聯。
外鍵(foreign key) 外鍵爲某個表中的一列,它包含另外一個表的主鍵值,定義了兩個表之間的關係。
SELECT vend_name,prod_name,prod_price FROM vendors AS v,products AS p--全部表 WHERE v.vend_id=p.vend_id-- 鏈接方式:equijoin,等值鏈接,又稱內部聯結 ORDER BY vend_name,prod_name; 徹底限定列名消除二義性!! SELECT vend_name,prod_name,prod_price FROM vendors INNER JOIN products ON vendors.vend_id=products.vend_id; //多個表。列出全部,而後關聯!!
其實,對於這種聯結(等值鏈接、內部鏈接)可使用稍微不一樣的語法來明確指定聯結的類型。FROM A,B WHERE A.col1=B.col2
能夠簡寫爲:inner join。聯結是SQL中最重要最強大的特性
使用哪一種語法? ANSI SQL規範首選INNER JOIN語法,鏈接條件。
別名除了用於列名和計算字段外,SQL還容許給表名起別名。
縮短SQL語句;
容許在單條SELECT語句中屢次使用相同的表。自鏈接
--物品有問題,該供應商的其餘商品是否也有問題 SELECT prod_id,prod_name FROM products WHERE vend_id=(SELECT Vend_id FROM products WHERE prod_id='DTNTR') --子查詢 -- 聯結 SELECT p1.prod_id,p1.prod_name FROM products AS p1,products AS p2 WHERE p1.vend_id=p2.vend_id AND p2.prod_id='DTNTR' --級聯操做和過濾數據。
聯結包含了那些在相關表中沒有關聯行的行。這種類型的聯結稱爲外部聯結,須要與left或者right來指明
在使用OUTER JOIN語法時,必須使用RIGHT或LEFT關鍵字指定包括其全部行的表(RIGHT指出的是OUTER JOIN右邊的表,而LEFT指出的是OUTER JOIN左邊的表)
SELECT customers.cust_id,COUNT(orders.order_num) AS num_ord FROM customers RIGHT OUTER JION orders ON orders.cust_id=customers.cust_id
應該老是提供聯結條件,不然會得出笛卡兒積。
MySQL也容許執行多個查詢(多條SELECT語句),並將結果做爲單個查詢結果集返回,union
或者複合查詢(compound query),組合查詢和多個WHERE條件
所需作的只是給出每條SELECT語句,在各條語句之間放上關鍵字UNION。UNION中的每一個查詢必須包含相同的列、表達式或彙集函數,由於返回的結果合爲一個表
--UNION從查詢結果集中自動去除了重複的行 SELECT vend_id,prod_id,prod_price FROM products WHERE prod_price<=5 UNION ALL--保留重複 SELECT vend_id,prod_id,prod_price FROM proucts WHERE vend_id IN(1001,1002) ORDER BY vend_id,prod_price;--能使用一條ORDER BY子句,它必須出如今最後一條SELECT語句以後 ----等價於多個where條件 SELECT vend_id ,prod_id,prod_price FROM products WHERE prod_price<=5 OR vend_id IN (1001,1002)
UNION幾乎老是完成與多個WHERE條件相同的工做。UNION ALL爲UNION的一種形式,它完成WHERE子句完成不了的工做。若是確實須要每一個條件的匹配行所有出現(包括重複行),則必須使用UNION ALL而不是WHERE。
在用UNION組合查詢時,只能使用一條ORDER BY子句,它必須出如今最後一條SELECT語句以後
CREATE TABLE product_notes( note_id int NOT NULL AUTO_INCREMENT, prod_id char(10) NOT NULL, note_date datetime NOT NULL, note_text text NULL, PRIMARY KEY(note_id), FULLTEXT(note_text) )ENGINE=MyISAM;
MyISAM支持全文本搜索(對結果排序,較高優先級的行先返回,自帶停用詞列表(stopword)),而InnoDB不支持
子句FULLTEXT(列名稱)
的指示對它進行索引,先導入,後定義索引,在索引以後,使用兩個函數Match()和Against()執行全文本搜索,其中Match()指定被搜索的列,Against()指定要使用的搜索表達式。
SELECT note_text FROM product_notes WHERE Math(note_text) Against('rabbit') AS rank; -- 效果上等價於LIKE ‘%rabbit%’,但效率不一樣。 SELECT note_text FROM product_notes WHERE note_text LIKE '%rabbit%';
INSERT INT Customers(能夠指定列名順序) VALUES(a),VALUES(b);-- 插入多個行
老是使用列的列表。插入時提升總體性能,可使用INSERT LOW_PRIORITY INTO
插入檢索出的數據 insert select,列的位置。
INSERT INTO customers(cust_id,cust_contact,cust_email,cust_name) SELECT cust_id,cust_contact,cust_email,cust_name FROM custnew;
UPDATE (IGNORE) customers-- 表名 SET cust_email='xxx@ffdd.com',cust_name='ddd' WHERE cust_id=10004;
不要省略WHERE子句(對update和delete都有效),UPDATE語句老是以要更新的表的名字開始.
DELETE FROM要求指定從中刪除數據的表名。WHERE子句過濾要刪除的行。
DELETE FROM customers WHERE cust_id=10004;
DELETE不須要列名或通配符。DELETE刪除整行而不是刪除列。爲了刪除指定的列,請使用UPDATE語句。
更快的刪除:truncate:TRUNCATE實際是刪除原來的表並從新建立一個表,而不是逐行刪除表中的數據在對UPDATE或DELETE語句使用WHERE子句前,應該先用SELECT進行測試,保證它過濾的是正確的記錄,以防編寫的WHERE子句不正確。應該使用引用完整性。使用默認值而不是NULL值
CREATE TABLE orders( order_num int NOT NULL AUTO_INCREMENT, cust_id int NOT NULL DEFAULT 1,-- 默認值 PRIMARY KEY(order_num) )ENGINE=InnoDB;
NULL爲默認設置.使用的最簡單的編號是下一個編號.AUTO_INCREMENT;
每一個表只容許一個AUTO_INCREMENT列,並且它必須被索引(如,經過使它成爲主鍵)。經過last_insert_id()函數
得到最後一個AUTO_INCREMENT.存儲引擎負責建立表等操做。
在表的設計過程當中須要花費大量時間來考慮,以便後期不對該表進行大的改動。
更新表 alter table
ALTER TABLE vendors ADD vend_phone CHAR(20);-- 增長列。 ALTER TABLE vendors DROP COLUMN vend_phone;
ALTER TABLE的一種常見用途是定義外鍵
ALTER TABLE order_items ADD CONSTRAINT fk_item_orders FOREIGN KEY(order_num) REFERECES orders(order_num);
使用ALTER TABLE要極爲當心,應該在進行改動前作一個完整的備份,沒有撤回操做。
刪除表:DROP TABLE 表名
重命名錶:RENAME TABLE 原來的表名 TO 新的表名
RENAME TABLE backup_a TO a, backup_b TO b;
視圖是虛擬的表。與包含數據的表不同,視圖只包含使用時動態檢索數據的查詢。
視圖做用:
視圖自己不包含數據,所以它們返回的數據是從其餘表中檢索出來的。在添加或更改這些表中的數據時,視圖將返回改變過的數據。
視圖用CREATE VIEW語句來建立。
SHOW CREATE VIEW viewname
其語法爲DROP VIEW viewname;
視圖更新:先drop後create或者:CREATE OR REPLACE VIEW
視圖的最多見的應用之一是隱藏複雜的SQL;視圖的另外一常見用途是從新格式化檢索出的數據。視圖對於簡化計算字段的使用特別有用。
CREATE VIEW product_customers AS SELECT cust_name,cust_contact,prod_id FROM customers,orders,order_items WHERE customers.cust_id=orders.cust_id AND order_items.order_num=orders.order_num;-- 鏈接條件 -- 體會,這兒就是將鏈接以後的邏輯的表做爲視圖 -- 應用 SELECT * FROM product_customers; SELECT cust_name,cust_contact FROM product_customers WHERE prod_id='TNT2'; -- 利用視圖,可一次性編寫基礎的SQL,而後根據須要屢次使用。做用相似於函數 CREATE VIEW location AS SELECT Concat(RTrim(vend_name),' (',RTrim(vend_country),' )') AS title FROM vendors ORDER BY vend_name; SELECT * FROM location;-- 應用視圖 -- 用視圖過濾不想要的數據 CREATE VIEW list AS SELECT cust_id,cust_name,cust_email FROM customers WHERE cust_eamil IS NOT NULL; -- SELECT * FROM list;-- WHERE子句與WHERE子句將自動合併。 CREATE VIEW infomation AS SELECT order_num,prod_id,quantity,item_price,quentity*item_prices AS total_price FROM order_items; -- 應用 SLECT * FROM infomation WHERE order_num=20005;
基本上能夠說,若是MySQL不能正確地肯定被更新的基數據,則不容許更新圖(包括插入和刪除視)。這實際上意味着,若是視圖定義中有如下操做,則不能進行視圖的更新:GROUP BY 、JOIN、UNION、彙集函數(MIN(),COUNT(),SUM(),DISTINCT)
存儲過程簡單來講,就是爲之後的使用而保存的一條或多條MySQL語句的集合。可將其視爲批文件,雖然它們的做用不只限於批處理。
MySQL稱存儲過程的執行爲調用,CALL
CALL product_pricing( @pricelow, @pricehigh, @price_average);-- 調用。 -- -- -- MYSQL 調用時須要修改結束分割符號。 DELEMITER // CREATE PROCEDURE prices() BEGIN SELECT Avg(prod_price) AS price_avg FROM products; END// DELEMITER ; -- 應用 CALL prices(); -- 刪除 DROP PROCEDURE IF EXISTS prices;
帶參數的存過程
-- 聲明變量 ;DECLARE price_low DECIMAL(8,2); DELEMITER // CREATE PROCEDURE prices( OUT p1 DECIMAL(8,2), OUT ph DECIMAL(8,2)) BEGIN SELECT MIN(prod_price) INTO p1 FROM products; SELECT MAX(prod_price) INTO ph FROM products; END // DELEMITER ; CALL prices(@price_low,@proce_high);全部MySQL變量都必須以@開始。 -- 以上調用不顯示任何的數據,它返回變量; 應用 SELECT @price_low; -- COMMENT關鍵字 SHOW CREATE PROCEDURE
須要在檢索出來的行中前進或後退一行或多行。這就是使用遊標的緣由。遊標(cursor)是一個存儲在MySQL服務器上的數據庫查詢,它不是一條SELECT語句,而是被該語句檢索出來的結果集。MySQL遊標只能用於存儲過程(和函數)。使用FETCH來讀取所需數據
BEGIN DECLARE o INT; DECLARE done BOOLEAN DEFAULT 0; DECLARE order_nums CURSOR FOR -- 聲明遊標 ,是一種類型。 SELECT order_num FROM orders; DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET done=1; --使用 OPEN order_nums; --循環 REPEAT FETCH order_nums INTO o; UNTIL done END REPEAT; --關閉 CLOSE order_nums; END; -- SQLSTATE'02000'是一個未找到條件
應用場景:
觸發器是MySQL響應如下語句(DELETE
、INSERT
、UPDATE
)而自動執行的一條MySQL語句(或位於BEGIN和END語句之間的一組語句).
CREATE TRIGGER new_product AFTER INSERT ON products FOR EACH ROW SELECT 'product added'; -- 刪除,觸發器不支持更新 DROP TRIGGER new_product;
只有表才支持觸發器,視圖不支持(臨時表也不支持)。每一個表最多支持6個觸發器(每條INSERT、UPDATE和DELETE的以前和以後)
CREATE TRIGGER new_order AFTER INSERT ON orders FOR EACH ROW SELECT NEW.order_num;-- FOR EACH ROW 跟具體的SQL語句。 -- 應用 INSERT INTO orders(order_date,cust_id) VALUES(Now(),10001); -- 返回值就是觸發器定義的內容。 -- DELETE 觸發器 CREATE TRIGGER delete_order BEFORE DELETE ON orders FOR EACH ROW BEGIN INSERT INTO archive_orders VALUES(OLD.order_num,OLD.order_date,OLD.cust_id); END -- 引用一個名爲OLD的虛擬表 -- UPDATE 觸發器的應用,數據驗證 CREATE TRIGGER update_vendor BEFORE UPDATE ON vendors FOR EACH ROW SET NEW.vend_state=Upper(NEW.vend_state)
觸發器的一種很是有意義的使用是建立審計跟蹤。使用觸發器,把更改(若是須要,甚至還有以前和以後的狀態)記錄到另外一個表很是容易.
事務(transaction)指一組SQL語句;
事務處理用來管理INSERT、UPDATE和DELETE語句,不能回退SELECT、CREATE、DROP。
SELECT * FROM order_totals; START TRANSACTION; DELETE FROM order_totals; SELECT * FROM order_totals; ROLLBACK;-- 回退到START TRANSACTION DELETE FROM order_items WHERE order_num=20001; DELETE FROM orders WHERE order_num=23334; SELECT * FROM order_totals; -- 提交。 COMMIT;
隱含提交(implicit commit),即提交(寫或保存)操做是自動進行的。在事務處理時,提交不會隱含地進行.
爲了支持回退部分事務處理,必須能在事務處理塊中合適的位置放置佔位符。這樣,若是須要回退,能夠回退到某個佔位符。這些佔位符稱爲保留點SAVEPOINT
SAVEPOINT delete1; ROLLBACK TO delete1;-- 保留點越多越好。RELEASE SAVEPOINT
更改默認的提交行爲(鏈接專用):SET autocommit=0;
COLLATE
:規定字符如何比較的指令。SHOW CHARACTER SET; SHOW COLLATION; SHOW VARIABLES LIKE 'character%' -- 建立表時指定字符集和校對。 -- 當不指定COLLATE,則使用數據庫默認。 CREATE TABLE mytable( column1 INT, columns2 VARCHAR(10) )DEFAULT CHARACTER SET hebrew COLLATE hebrew_general_ci;
校對在對用ORDER BY子句 檢索出來的數據排序時起重要的做用。
COLLATE可用於ORDER BY
、GROUP BY
、HAVING
、彙集函數、別名等。
SELECT * FROM customers ORDER BY lastname,firstname COLLATE latin1_general_cs;
訪問控制:設置權限,使用GRANT語句
MySQL用戶帳號和信息存儲在名爲mysql
的庫中.
USE mysql; SELECT user FROM user;
MySQL的權限用用戶名和主機名結合定義,不指定採用默認值
CREATE USER 'yyq' identified by '密碼' ;-- 能夠不指定密碼,指定時須要用identified by RENAME USER yyq TO 'new_name';
GRANT
:權限名稱-數據庫或者表-用戶名。回收權限:revoke
GRANT SELECT on test.* TO yyq; REVOKE SELECT ON test.* TO yyq;
GRANT和REVOKE可在幾個層次上控制訪問權限:
整個服務器,使用GRANT ALL和REVOKE ALL;
整個數據庫,使用ON database.*;
特定的表,使用ON database.table;
特定的列;
特定的存儲過程。
簡化屢次受權:GRANT SELECT,INSERT ON test.* TO yyq
更改口令
SET PASSWORD FOR yyq=Password('ddd');
mysqlhotcopy,BACKUP TABLE
analyze table user; check table user;
查看日誌:1.錯誤日誌·hostname.err
;2.查詢日誌hostname.log
;3.二進制日誌(更新):hostname-bin
;4.慢查詢日誌hostname-slow.log
SHOW VARIABLES;SHOW STATUS;SHOW PROCESSLIST
。
老是有不止一種方法編寫同一條SELECT語句。應該試驗聯結、並、子查詢等,找出最佳的方法
使用EXPLAIN
命令檢查SQL執行過程。
若是數值是計算(求和、平均等)中使用的數值,則應該存儲在數值數據類型列中。若是做爲字符串(可能只包含數字)使用,則應該保存在串數據類型列中。 不使用引號 與串不同,數值不該該括在引號內。