--where子句操做符:html
= | 等於 |
<> | 不等於(標準語法) |
!= | 不等於(非標準語法,可移植性差) |
< | 小於 |
<= | 小於等於 |
> | 大於 |
>= | 大於等於 |
between | 在指定的兩個值之間 |
IS NULL | 空值檢查 |
IN(a, b) | 在a與b之間 |
NOT | 注意NOT在複雜語句中的應用,好比NOT IN(A, B),在簡單語句中,NOT沒有什麼特別之處,可是在複雜語句中,顯得很重要mysql 在MySQL中使用NOT對IN、BETWEEN和EXISTS子句取反,這個多數其餘DBMS容許使用NOT對各類條件取反有很大差異git |
--通配符:%與_程序員
% | %s正則表達式 s%sql s%e數據庫 |
%匹配的是單個或多個字符 |
_ | _s瀏覽器 s_安全 s_e服務器 |
_匹配的是單個字符而不是多個字符 |
--正則表達式:注意[]是另外一種形式的OR,好比[123]Ton是[1|2|3]Ton的縮寫,若是不使用[],則會匹配出其餘行的數據,
如:1|2|3 ton就會檢索出Jet 1000
[1-9]、[a-Z],若是是匹配一些特殊的字符要使用\\進行轉義,如\\.表示查找. \\\表示查找\
空白元字符:\\f換頁 \\n換行 \\r回車 \\t製表 \\v縱向製表
--匹配字符類:
[:alnum:] | 任意字母和數字(同[a-xA-Z0-9]) |
[:alpha:] | 任意字符(同[a-zA-Z]) |
[:blank:] | 空格和製表(同[\\t]) |
[:cntrl:] | ASCII控制字符(ASCII 0到31和127) |
[:digit:] | 任意數字(同[0-9]) |
[:graph:] | 與[:print:]相同,但不包括空格 |
[:lower:] | 任意小寫字母(同[a-z]) |
[:print:] | 任意可打印的字符 |
[:punct:] | 既不在[:alnum:]又不在[:cntrl:]中的任意字符 |
[:space:] | 包括空格在內的任意空白字符(同[\\f\\n\\r\\t\\v]) |
[:upper:] | 任意大寫字母([A-Z]) |
[:xdigit:] | 任意十六進制數字(同[a-fA-F0-9]) |
匹配多個實例:
* | 0個或多個匹配 |
+ | 1個或多個匹配 |
? | 0個或1個匹配(等於{1,}) |
{n} | 指定數目的匹配 |
{n,} | 很多於指定數目的匹配 |
{n,m} | 匹配數目的範圍(m不超過255) |
--建立拼接字段
MySQL中使用concat(a,b)函數來拼接兩個列,可是多數DBMS使用+或||來實現拼接
Trim函數去掉串左右兩邊的空格,RTrim()函數去掉值右邊的全部空格,LTrim()函數去掉值左邊的全部空格
--使用別名
關鍵字是as,固然as能夠省略,但儘可能不省略,根據經驗,有時候普as不寫會報錯
--執行算術計算
操做符:+加-減*乘/除
select NOW()返回當前日期和時間
--使用數據處理函數
文本處理函數:
Left() | 返回串左邊的字符 |
Length() | 返回串的長度 |
Locate() | 找出串的一個字串 |
Lower() | 將串轉換爲小寫 |
LTrim() | 去掉串左邊的空格 |
Right() | 返回串右邊的字符 |
RTrim() | 去掉串右邊的空格 |
Soundex() | 返回串的SOUNDEX的值 |
SubString() | 返回字串的字符 |
Upper() | 將串轉換爲大寫 |
日期和時間處理函數:
AddDate() | 增長一個日期(天、周等) |
AddTime() | 增長一個時間(時、分等) |
CurDate() | 返回當前的日期 |
CurTime() | 返回當前的時間 |
Date() | 返回日期時間的日期部分 |
DateDiff() | 計算兩個日期之差 |
Date_Add() | 高度靈活的日期運算函數 |
Date_Format() | 返回一個格式化的日期或時間串 |
Day() | 返回一個日期的天數部分 |
DayOfWeek() | 對於一個日期,返回對應的星期幾 |
Hour() | 返回一個時間的小時部分 |
Minute() | 返回一個時間的分鐘部分 |
Month() | 返回一個日期的月份部分 |
Now() | 返回當前日期和時間 |
Second() | 返回一個時間的秒部分 |
Time() | 返回一個日期時間的時間部分 |
Year() | 返回一個日期的年份部分 |
數值處理函數:
Abs() | 返回一個數的絕對值 |
Cos() | 返回一個角度的餘弦 |
Exp() | 返回一個數的指數值 |
Mod() | 返回一個除操做的餘數 |
Pi() | 返回圓周率 |
Rand() | 返回一個隨機數 |
Sin() | 返回一個角度的正弦 |
Sqrt() | 返回一個數的平方根 |
Tan() | 返回一個角度的正切 |
----彙總數據
--彙集函數:
AVG() | 返回某列的平均值 |
COUNT() | 返回某列的行數 |
MAX() | 返回某列的最大值 |
MIN() | 返回某列的最小值 |
SUM() | 返回某列值之和 |
--彙集不一樣值
上述的5個彙集函數均可以以下使用:
一、對全部的行執行計算,指定ALL參數或不給參數(由於ALL是默認行爲)
二、只包含不一樣的值,指定DISTINCT參數
若是指定列名,則DISTINCT只能用於COUNT(),按技術上來講,DISTINCT能夠用於MAX()和MIN(),可是沒有意義
--組合彙集函數
意思就是select能夠包含多個彙集函數
--分組數據
關鍵字GROUP BY
規定:
一、GROUP BY子句能夠包含任意數目的列
二、若是在GROUP BY子句中嵌套了分組,數據將在最後規定的分組上進行彙總,換句話說,在創建分組時,指定的全部列都一塊兒計算(因此不能從個別的列取回數據)
三、GROUP BY子句中列出的每一個列都必須時檢索列或者有效的表達式(但不能是彙集函數),若是在select中使用表達式,則必須在GROUP BY子句中指定
相同的表達式,不能使用別名
四、除彙集計算語句外,select語句中的每一個列都必須在GROUP BY子句中給出
五、若是分組列中具備NULL值,則NULL將做爲一個分組返回。若是列中有多行NULL值,它們將分爲一組
六、GROUP BY子句必須出如今WHERE子句以後,ORDER BY子句以前
使用ROLLUP,使用WITH ROLLUP關鍵字,能夠獲得每一個分組以及每一個分組彙總界別級別(針對每一個分組)的值
過濾分組:
關鍵字HAVING
除了能用GROUP BY分組數據外,MySQL還容許使用過濾分組,規定包括哪些分組,排除哪些分組。由於WHERE沒有分組的概念,因此WHERE過濾指定的是行而不是分組。
目前爲止所學過的全部類型的WHERE子句均可以用HAVING來替代,惟一的差異是WHERE是過濾行,而HAVING過濾分組。過濾是基於分組彙集值而不是特定行值的。
另外一種思惟區分HAVING和WHERE:
WHERE在數據分組前進行過濾,HAVING在數據分組後進行過濾。這是一個重要區別,WHERE排除的行不包括在分組中,這可能會改變計算值,從而影響HAVING子句中基於這些值過濾掉的分組。
分組和排序:
ORDER BY | GROUP BY |
排序產生的輸出 | 分組行。但輸出可能不是分組的順序 |
任意列均可以使用(甚至非選擇的列也可使用) | 只可能使用選擇列或表達式列,並且必須使用每一個選擇列表達式 |
不必定須要 | 若是和彙集函數一塊兒使用列(或表達式),則必須使用 |
PS:通常在使用GROUP BY子句時,應該也給出ORDER BY子句。這是保證數據正確排序的惟一方法,千萬不要依賴於GROUP BY排序數據
SELECT子句順序:
子句 | 說明 | 是否必須使用 |
SELECT | 要返回的列或表達式 | 是 |
FROM | 從中檢索數據的表 | 僅在從表選擇數據時使用 |
WHERE | 行級過濾 | 否 |
GROUP BY | 分組說明 | 僅在按組計算彙集時使用 |
HAVING | 組級過濾 | 否 |
ORDER BY | 輸出排序順序 | 否 |
LIMIT | 要檢索的行數 | 否 |
--使用子查詢
在select中建立多個select
利用子查詢進行過過濾
做爲計算字段使用子查詢,就是子查詢做爲一個字段
----聯結表
PS:叉聯結(cross join),有時咱們會聽到返回成爲叉聯結的笛卡爾積的聯結類型
--內部聯結
目前所用的聯結成爲等值聯結(equijoin),基於兩個表之間的相等的測試,又稱爲內部聯結。
ANSI SQL規範首選INNER JOIN語法,此外儘管使用WHERE子句定義聯結的確比較簡單,可是使用明確的聯結語法可以確保不會忘記聯結條件,有時候這樣作也能影響性能。
----建立高級聯結
除了使用別名引用唄檢索的表列,給列起別名的用法以下,寫的緣由主要是沒見過這種concat的用法:
SELECT Concat(RTrim(vend_name), '(', RTrim(vend_country), ')') AS vend_title FROM vendors ORDER BY vend_name
----使用不一樣類型的聯結
內部聯結或等值聯結都是簡單聯結,其實還有其餘聯結,分別是自聯結、天然聯結和外部聯結
--自聯結
用自聯結而不用子查詢:天然聯結一般做爲外部語句用來替代從相同表中檢索數據時使用的子查詢語句。雖然最終的結果是同樣的,但有時候處理聯結遠比處理子查詢快得多。應該試一下兩種方法,以肯定哪種的性能更好。
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';
--天然聯結
PS:事實上,迄今爲止,咱們創建的每一個內部聯結都是天然聯結,極可能咱們永遠都不會用到不是天然聯結的內部聯結
--外部聯結
聯結包含了那些在相關表中沒有關聯行的行,這種類型的聯結稱爲外部聯結
select customer.cust_id, orders.order_num from customers inner join orders on customers.cust_id = orders.cust_id; select customer.cust_id, orders.order_num from customers left join orders on customers.cust_id = orders.cust_id;
PS:
一、沒有*=操做符,MySQL不支持簡化字符*=和=*的使用,這兩種操做符在其餘DBMS中很流行
二、外部聯結的類型:存在兩種基本的外部聯結形式:左外部聯結和右外部聯結。它們之間的惟一差異是所關聯的表的順序不一樣。換句話說,左外部聯結可經過顛倒from或where子句中表的順序轉化爲右外部聯結。所以,兩種類型的外部聯結可互換使用,而究竟使用哪種純粹是根據方便而定。
--使用帶彙集函數的聯結
select customer.cust_id, customer.cust_name, count(orders.order_num) as num_ord from customer inner join orders on customer.cust_id = orders.cust_id group by customer.cust_id
--使用聯結和聯結條件
要點:
一、注意所使用的聯結類型。通常咱們使用內部聯結,但使用外部聯結也是有效的
二、保證使用正確的聯結條件,不然將返回不正確的數據
三、應該老是提供聯結條件,不然會得出笛卡爾積
四、在一個聯結中能夠包含多個表,甚至對於每一個聯結能夠採起不一樣的聯結類型。雖然這樣作是合法的,通常也頗有用,但應該在一塊兒測試它們前,分別測試每一個聯結。這將是故障排除更爲簡單。
----組合查詢
--組合查詢
MySQL容許執行多個查詢(多條select語句),並將結果做爲單位查詢結果集返回。這些組合查詢一般成爲並(union)或複合查詢(compound query)。
有兩種基本狀況,其中須要使用組合查詢:
一、在單個查詢中從不一樣的表返回相似結構的數據;
二、對單個表執行多個查詢,按單個查詢返回數據。
組合查詢和多個where條件:多數狀況下,組合相同表的兩個查詢完成的工做與具備多個where子句條件的單條查詢完成的工做相同。換句話說,任何具備多個where子句的select語句均可以做爲一個組合查詢給出,在如下段落中能夠看到這一點。這兩種技術在不一樣的查詢中,性能也不一樣。所以,應該試一下兩種技術,以肯定對特定的查詢哪種性能更好。
--使用union建立組合查詢
給出每條select語句,在各條語句之間放上關鍵字union,下述寫法就是將兩個select查詢的東西合併在一塊兒(3列)
select vend_id, prod_id, prod_price from products where prod_price <= 5 union select vend_id, prod_id, prod_price from products where vend_id in (1001,1002)
簡單例子中,union比where複雜,可是遇到複雜的過濾條件,或者從多個表(而不是單個表)中檢索數據的情形,使用union可能會使處理更簡單。
--union規則
注意:
一、union必須由兩條以上的select語句組成,語句之間用關鍵字union分隔(所以,若是組合4條select語句,將要使用3個union關鍵字)
二、union中的每一個查詢必須包含相同的列、表達式或彙集函數(不過各個列不須要以相同的次序列出)
三、列數據類型必須兼容:類型沒必要徹底相同,但必須是DBMS能夠隱含地轉換的類型(例如,不一樣的數值類型或不一樣的日期類型)
若是遵照了這些基本規則或限制,則能夠將並用於任何數據檢索任務。
--包含或取消重複的行
在union的默認行爲中,是取消了重複行的,可是可使用union all來返回全部匹配行
ps:union與where:union幾乎老是完成與多個where條件相同的工做。union all爲union的一種形式,它完成where子句完成不了的工做。若是確實須要每一個條件的匹配行所有出現(包括重複行),則必須使用union all而不是where。
--對組合查詢結果排序
在用union組合查詢時,只能使用一條order by子句,它必須出如今最後一條select語句以後。對於結果集,不存在用一種方式排序一部分,而有用另外一種方式排序另外一部分的狀況,所以不容許使用多條order by子句。
ps:組合不一樣的表:使用union的組合查詢能夠應用不一樣的表。
----全文本搜索
並不是全部引擎都支持全文本搜索:MySQL支持幾種基本的數據庫引擎。並不是全部的引擎都支持該文章所描述的全文本搜索。兩個最常使用的引擎爲MyISAM和InnoDB。前者支持全文本搜索,然後者不支持。
like和正則表達式等搜索機制存在幾個重要的限制:
一、性能:通配符和正則表達式匹配一般要求MySQL嘗試匹配表中全部行(並且這些搜索極少使用)。所以,因爲被搜索行數不斷增長,這些搜索可能很是耗時
二、明確控制:使用通配符和正則表達式匹配,很難(並且並不老是能)明確地控制匹配什麼和不匹配什麼。例如,指定一個詞必須匹配,一個詞必須不匹配,而一個詞僅在第一個詞確實匹配的狀況下才能夠匹配或者才能夠不匹配
三、智能化的結果:雖然基於通配符和正則表達式的搜索提供了很是靈活的搜索,但它們都不能提供一種智能化的選擇結果的方法。例如,一個特殊詞的搜索將會返回多個包含該詞的全部行,而不區分包含單個匹配的行和包含多個匹配的行(按照可能時更好的匹配來排列它們)。相似,一個特殊詞的搜索將不會找出不包含該詞但包含其餘相關詞的行。
全部這些限制以及更多的限制均可以用全文本搜索來解決。在使用全文本搜索時,MySQL不須要分別查看每一個行,不須要分別分析和處理每一個詞。MySQL建立指定列中各詞的一個索引,搜索能夠針對這些詞進行。這樣,MySQL能夠快速有效地決定哪些詞匹配(哪些行包含它們),哪些詞不匹配,它們匹配的頻率,等等。
--使用全文本搜索
爲了進行全文本搜索,必須索引被搜索的列,並且要隨着數據的改變不斷地從新搜索。在對錶列進行適當設計後,MySQL會自動進行全部的索引和從新索引。
在索引以後,select可與match()和against()一塊兒使用以實際執行執行搜索。
-------演示FULLTEXT子句的使用 create table productnotes ( note_id int not null auto_increment, prod_id char(10) not null, note_date datetime not null, PRIMARY KEY(note_id), FULLTEXT(note_text) ) ENGINE=MyISAM;
ps:不要在導入數據時使用FULLTEXT:更新索引要花時間,雖然不是不少,但畢竟要花時間。若是正在導入數據到一個新表,此時不該該啓用FULLTEXT索引。應該首先導入全部數據,而後再修改表,定義FULLTEXT。這樣有助於更快地導入數據(並且使索引數據的總時間小於在導入每行時分別進行索引所須要的總時間)。
--進行全文本搜索
在索引以後,使用兩個函數match()和against()執行全文本搜索,其中match()指定被搜索的列,against()指定要使用的搜索表達式。
關於match()和against()函數的解釋:
函數 MATCH() 對照一個文本集(包含在一個 FULLTEXT 索引中的一個或多個列的列集)執行一個天然語言搜索一個字符串。搜索字符串作爲 AGAINST() 的參數被給定。搜索以忽略字母大小寫的方式執行。對於表中的每一個記錄行,MATCH() 返回一個相關性值。即,在搜索字符串與記錄行在 MATCH() 列表中指定的列的文本之間的類似性尺度。當 MATCH() 被使用在一個 WHERE 子句中時 (參看上面的例子),返回的記錄行被自動地以相關性從高到底的次序排序。相關性值是非負的浮點數字。零相關性意味着不類似。相關性的計算是基於:詞在記錄行中的數目、在行中惟一詞的數目、在集中詞的所有數目和包含一個特殊詞的文檔(記錄行)的數目。它也能夠執行一個邏輯模式的搜索。
ps:使用完整的match()說明:傳遞給match()的值必須與FULLTEXT()定義中的相同。若是指定多個列,則必須列出它們(並且次序正確);
搜索不區分大小寫:除非使用binary方式,不然全文本搜索不區分大小寫;
排序多個搜索項:若是指定多個搜索項,則包含多數匹配詞的那些行將具備比包含較少詞(或僅有一個匹配)的那些行高的等級值。
全文本搜索時對結果排序,具備較高等級的行先返回。全文本提供了簡單like搜索不能提供的功能。並且因爲數據是索引,全文本搜索還至關快。
--使用查詢擴展
在使用查詢擴展時,MySQL對數據和索引進行兩遍掃描來完成搜索:
一、首先,進行一個基本的全文本搜索,找出與搜索條件匹配的全部行
二、其次,MySQL檢查這些匹配行並選擇全部有用的詞
三、再其次,MySQL再次進行全文本搜索,此次不只使用原來的條件,並且還使用全部有用的詞。
查詢擴展增長了返回的行數,,但這樣作也增長了實際上並不想要的數目。
ps:行越多越好:表中的行越多(這些行中的文本就越多),使用查詢擴展返回的結果越好。
--布爾文本搜索
以布爾方式,能夠提供關於以下內容的細節:
一、要匹配的詞
二、要排斥的詞(若是某行包含這個詞,則不反悔該行,即便它包含其餘指定的詞也是如此)
三、排列提示(指定某些詞比其餘詞更重要,更重要的詞等級更高)
四、表達式分組
五、另一些內容
ps:即便沒有FULLTEXT索引也可使用:布爾方式不一樣於迄今爲止使用的全文本搜索語法的地方在於,即便沒有定義FULLTEXT索引,也可使用它。但這是一種很是緩慢的操做(其性能將隨着數據量的增長而下降)
IN BOOLEAN MODE的行爲差別
布爾操做符 | 說明 |
+ | 包含,詞必須存在 |
- | 排除,詞必須不出現 |
> | 包含,並且增長等級值 |
< | 包含,且減小等級值 |
() | 把詞組成子表達式(容許這些子表達式做爲一個組被包含、排除、排列等) |
~ | 取下一個詞的排序值 |
* | 詞尾的通配符 |
"" | 定義一個短語(與單個詞的列表不同,它匹配整個短語以便包含或排除這個短語) |
ps:排列而不排序:在布爾方式中,不按等級值降序排序返回的行
-全文本搜索的使用說明
一、在索引全文本數據時,短詞被忽略且從索引中排除。短語定義爲那些具備3個或3個如下字符的詞(若是須要,這個數目能夠更改)
二、MySQL帶有一個內建的非用詞(stopword)列表,這些詞在索引全文本數據時老是被忽略。若是須要,能夠覆蓋這個列表
三、許多詞出現的頻率很高,搜索它們沒有用處(返回太多的結果)。所以,MySQL規定了一條50%規則,若是一個詞出如今50%以上的行中,則將它做爲一個非用詞忽略。50%規則不用於IN BOOLEAN MODE
四、若是表中的行數少於3行,則全文本搜索不返回結果(由於每一個詞或者不出現,或者至少出如今50%的行中)
五、忽略此中的單引號。例如,don't索引爲dont
六、不具備詞分隔符(包括日語和漢語)的語言不能恰當地返回全文本搜索結果
七、僅在MyISAM數據庫引擎中支持全文本搜索
----插入數據
--數據插入
插入能夠用幾種方式使用:
一、插入完整的行
二、插入行的一部分
三、插入多行
四、插入某些查詢的結果
插入及系統安全:可針對每一個表或每一個用戶,利用MySQL的安全機制機制禁止使用INSERT語句
--插入完整的行
insert into customers values (null, 'LeeMichael', '100 street', 'los angle', null, 'USA');
-----------------------------------
insert into customers(
cust_name,
cust_addr,
cust_city,
cust_country)
values ( 'LeeMichael', '100 street', 'los angle', 'USA');
ps:老是使用列的列表:通常不要使用沒有明確給出列的列表的INSERT語句。使用列的列表能使SQL代碼繼續發揮做用,即便表結構發生了變化。
仔細地給出值:無論使用哪一種INSERT語法,都必須給出values的正確數目。若是不提供列名,則必須給每一個表列提供一個值。若是提供列名,則必須對梅格列出的列給出一個值。若是不這樣,將產生一條錯誤信息,相應的行插入不成功。
省略列:若是表的定義容許,則能夠在INSERT操做中省略某些列。省略的列必須知足如下某個條件:
一、該列定義爲容許null值(無值或空值)
二、在表定義中給出默認值。這表示若是不給出值,將使用默認值
若是對錶中不容許null值且沒有默認值的列不給出值,則MySQL將產生一條錯誤消息,而且相應的行插入不成功。
提升總體性能:數據庫常常被多個客戶訪問,對處理什麼請求以及用什麼次序處理進行管理是MySQL的任務。INSERT操做可能很耗時(特別是有不少索引須要更新時),並且它可能下降等待處理的select語句的性能
若是數據檢索是最重要的(一般是這樣),則你能夠經過在INSERT和INTO之間添加關鍵字LOW_PRIORITY,指示MySQL下降INSERT語句的優先級,如:INSERT LOW_PRIORITY INTO,這也適用於UPDATE和DELETE。
--插入多個行
insert into customers( cust_name, cust_addr, cust_city, cust_country) values ( 'LeeMichael', '100 street', 'los angle', 'USA'); insert into customers( cust_name, cust_addr, cust_city, cust_country) values ( 'LGQMichael', '100 street', 'los angle', 'USA');
多個語句,用 ; 隔開
或者能夠這樣(這樣寫能夠提升性能):
insert into customers( cust_name, cust_addr, cust_city, cust_country) values ( 'LeeMichael', '100 street', 'los angle', 'USA'), ( 'LGQMichael', '100 street', 'los angle', 'USA'),
ps:提升insert的性能:此技術能夠提升數據庫處理的性能,由於MySQL用單條INSERT語句處理多個插入比使用多條INSERT語句快。
--插入檢索出的數據
新例子的說明:這個例子把一個名爲custnew的表中的數據導入customers表中。爲了試驗這個例子,應該首先建立和填充custnew表。custnew表的結構於customers表相同。在填充custnew時,不該該使用已經在customers中使用過的cust_id值(若是主鍵值重複,後續的INSERT操做將會失敗)或僅省略這列值讓MySQL在導入數據的過程當中產生新值。
insert into customers (cust_id, cust_contact, cust_email, cust_name, cust_addr, cust_city) select cust_id, cust_contact, cust_email, cust_name, cust_addr, cust_city from custnew
ps:INSERT SELECT中的別名:爲簡單起見,這個例子在INSERT和SELECT語句中使用了相同的列名。可是,不必定要求列名匹配。事實上,MySQL甚至不關心SELECT返回的列名。它使用的是列的位置,所以SELECT中的第一列(無論其列名)將用來填充表列中指定的第一列,第二列將用來填充表列中指定的第二個列,如此等等。這對於從使用不一樣列名的表中導入數據時很是有用的。
INSERT SELECT中SELECT語句中能夠包含where子句以過濾插入的數據。
----更新和刪除數據
--更新數據
爲了更新(修改)表中的數據,可以使用UPDATE語句。可採用兩種方式使用UPDATE:
一、更新表中特定行
二、更新表總全部行
ps:不要省略WHERE子句:在使用UPDATE時必定要注意細心。由於稍不注意,就會更新表中全部行。
UPDATE與安全:能夠限制和控制UPDATE語句的使用。
基本的UPDATE語句由3個部分組成,分別是:
一、要更新的表
二、列名和它們的新值
三、肯定要更新行的過濾條件
update customers set cust_email = 'lgq@163.com' where cust_id = 1005;
ps: 在UPDATE語句中使用子查詢:UPDATE語句中可使用子查詢,使得能用SELECT語句檢索出的數據更新列數據
IGNORE關鍵字:若是能用UPDATE語句更新多行,而且在更新這些行中的一行
--刪除數據
爲了從一個表中刪除(去掉)數據,使用delete語句。分爲兩種方式:
一、從表中刪除特定的行
二、從表中刪除全部行
ps:不要省略where子句:在使用delete時必定要注意細心。由於稍不注意,就會錯誤地刪除表中全部行。
delete與安全:能夠限制和控制delete語句的使用
刪除表的內容而不是表:delete語句從表中刪除行,甚至是刪除表中全部行。可是,delete不是刪除表自己。
更快的刪除:若是想從表中刪除全部行,不要使用delete。可使用TRUNCATE TABLE語句,它完成相同的工做,但速度更快(TRUNCATE實際是刪除原來的 表並不從新建立一個表,而不是逐行刪除表中的數據)
--更新和刪除的指導原則
許多SQL程序員使用UPDATE和DELETE時所遵循的習慣:
一、除非確實打算更新和刪除每一行,不然絕對不要使用不帶where子句的UPDATE和DELETE
二、保證每一個表都有主鍵,儘量想where子句那樣使用它(能夠指定各主鍵、多個值或值的範圍)
三、在對UPDATE或DELETE語句使用where子句前,應該先用SELECT進行測試,保證它過濾的是正確的記錄,以防編寫的where子句不正確
四、使用強制實施引用完整性的數據庫,這樣MySQL將不容許刪除與其餘相關聯的數據的行
ps:當心使用:MySQL沒有撤銷(undo)按鈕。應該很是當心地使用UPDATE和DELETE,不然你會發現本身更新或刪除了錯誤的數據。
----建立和操縱表
--建立表
方法:
一、使用具備交互式建立和管理表的工具
二、表也能夠直接用MySQL語句操縱
--表建立基礎
一、新表的名字,在關鍵字create table以後給出
二、表列的名字和定義,用逗號分隔開
create table customers ( cust_id int not null auto_increment, cust_name char(50) not null, primary key (cust_id) )ENGINE=InnoDB;
語句格式化:MySQL語句中忽略空格。語句能夠在一個長行上輸出,也能夠分紅許多行。它們的做用都相同。這容許你以最適合本身的方式安排語句的格式。強烈建議採用某種縮進格式。
處理現有的表:在建立新表時,指定的表名必須不存在,不然將出錯。若是要防止意外覆蓋已有的表,SQL要求首先手工刪除該表,而後再重建它,而不是簡單地用建立表語句覆蓋它。若是你僅想在一個表不存在時建立它,應該在表名後給出IF NOT EXISTS。這樣作不檢查已有表的模式是否與你打算建立的表模式相匹配。它只是查看錶名是否存在,而且僅在表名不存在時建立它。
--使用NULL值
NULL值就是沒有值或缺值。容許NULL值的列也容許在插入行時不給出該列的值。不容許NULL值的列不接受該列沒有值的行,換句話說,在插入或更新行時,該列必須有值。每一個表列或者是NULL列,或者是NOT NULL列,這種狀態在建立時由表的定義規定。
理解NULL:不要把NULL值與空串相混淆。NULL值是沒有值,它不是空串。若是指定 '' (兩個單引號,其間沒有字符),這在NOT NULL列中是容許的。空串是一個有效的值,它不是無值。NULL值用關鍵字而不是空串指定。
--主鍵再介紹
主鍵值必須惟一。即,表中的每一個行必須具備惟一的主鍵值。若是主鍵使用單個列,則它的值必須惟一。若是使用多個列,則這些列的組合值必須惟一。建立多個列組成的主鍵primary key(a, b)
主鍵能夠在建立表時定義,或者在建立表以後定義
ps:主鍵和NULL值:主鍵爲其值惟一標識表中每一個行的列。主鍵中只能使用不容許NULL值的列。容許NULL值的列不能做爲惟一標識。
--使用AUTO_INCREMENT
ATUO_INCREMENT告訴MySQL,本列每當增長一行時自動增量。每次執行一個INSERT操縱時,告訴MySQL自動對該列增量(從而纔有這個關鍵字),給該列賦予下一個可用的值。這樣給每一個行分配一個惟一的id,從而能夠用做主鍵。
每一個表只容許一個AUTO_INCREMENT列,並且它必須被索引(如,經過使它成爲主鍵)
ps:覆蓋AUTO_INCREMENT:若是一個列被指定爲AUTO_INCREMENT,則它須要使用特殊的值嗎?你能夠簡單地在INSERT語句中指定一個值,只要它是惟一的便可,該值將被用來替代自動生成的值。後續的增量將開始使用該手工插入的值
肯定AUTO_INCREMENT值:讓MySQL生成(經過自動增量)主鍵的一個缺點是你不知道這些值都是誰。
--指定默認值
create table orderitems ( order_num int not null, order_item int not null, prod_id char(10) not null, quantity int not null default 1, item_price decimal(8,2) not null, primary_key(order_num, order_item) )ENGINE=InnoDB;
上述代碼中就設置了quantity的默認值位1.
ps:不容許函數:與大多數DBMS不同,MySQL不容許使用函數做爲默認值,它只支持常量
使用默認值而不是NULL值:許多數據庫開發人員使用默認值而不是NULL值,特別是對用於計算或數據分組的列更是如此。
--引擎類型
與其餘DBMS同樣,MySQL有一個具體管理和處理數據的內部引擎。在你使用CREATE TABLE語句時,該引擎具體建立表,而在你使用SELECT語句或進行其餘數據庫處理時,該引擎在內部處理你的請求。多數時候,此引擎都隱藏在DBMS內,不須要過多關注它
但MySQL與其餘DBMS不同,它具備多種引擎。它打包多個引擎,這些引擎都隱藏在MySQL服務器內,全都能執行CREATE TABLE和SELECT等命令。這些引擎具備各自不一樣的功能和特性,爲不一樣的任務選擇正確的引擎能得到良好的功能和靈活性。若是省略ENGINE=語句,則使用默認引擎MyISAM,多數SQL語句都會默認使用它。但並非全部語句都默認使用它,這就是爲何ENGINE=語句很重要的緣由。
引擎介紹:
一、InnoDB是一個可靠的事務處理引擎,它不支持全文本搜索
二、MEMORY在功能等同於MyISAM,但因爲數據存儲在內存(不是磁盤)中,速度很快(特別適用於臨時表)
三、NyISAM是一個性能極高的引擎,它支持全文本搜索,但不支持事務處理。
引擎類型能夠混用。
ps:更多知識:所支持引擎的完整列表(及它們之間的不一樣),參閱https://dev.mysql.com/doc/refman/5.0/en/storage_engines.html
外鍵不能跨引擎:混用引擎類型有一個大缺陷。外鍵(用於強制實施引用完整性)不能跨引擎,即便用一個引擎的表不能引用具備使用不一樣引擎的表的外鍵。
--更新表
爲更新表定義,可以使用ALTER TABLE語句。可是,在理想狀態下,當表中存儲數據以後,該表就不該該再被更新。在表的設計過程當中須要花費大量時間來考慮,以便後期不對該表進行大的改動。
爲了使用ALTER TABLE更改表結構,必須給出下面的信息:
一、在ALTER TABLE以後給出要更改的表名(該表必須存在,不然將出錯)
二、所做更改的列表
ALTER TABLE vendors ADD vend_phone char(20); -------------------------------------- ALTER TABLE vendors DROP COLUMN vend_phone;
複雜表結構更改通常須要手動刪除過程,它設計如下步驟:
一、用新的列布局建立一個新表
二、使用INSERT SELECT語句從舊錶複製數據到新表,若有必要可以使用轉換函數和計算字段
三、檢驗包含所需數據的新表
四、重命名舊錶(若是肯定,能夠刪除它)
五、用舊錶原來的名字重命名新表
六、根據須要,從新建立觸發器、存儲過程、索引和外鍵
ps:當心使用ALTER TABLE:使用ALTER TABLE要極爲當心,應該在進行改動前作一個完整的備份(模式和數據的備份)。數據庫表的更改不能撤銷,若是增長了不須要的列,可能不能刪除它們。相似的,若是刪除了不該該刪除的列,可能會丟失該列中的全部數據。
--刪除表
DROP TABLE customers;
--重命名錶
使用RENAME TABLE語句能夠重命名一個表
RENAME TABLE backup_customers TO customers, backup_vendors TO vendors;
----使用視圖
視圖的一些常見應用:
一、重用SQL語句
二、簡單複雜的SQL操做。在編寫查詢後,能夠方便地重用它而沒必要知道它的基本查詢細節
三、使用表的組成部分而不是整個表
四、保護數據。能夠給用戶授予表的特定部分的訪問權限而不是整個表的訪問權限
五、更改數據格式和表示。視圖可返回與底層表的表示和格式不一樣的數據。
重點:視圖僅僅是用來查看存儲在別處的數據的一種設施。視圖自己不包含數據,所以它們返回的數據是從其餘表中檢索出來的。在添加或更改這些表中的數據時,視圖將返回改變過的數據。
ps:性能問題:由於視圖不包含數據,因此每次使用視圖時,都必須處理查詢執行時所需的任一個檢索。若是你用多個聯結和過濾建立一個複雜的視圖或者嵌套了視圖,可能會發現性能降低的很厲害。所以,在部署使用了大量視圖的應用前,應該進行測試。
--視圖的規則和限制
一、與表同樣,視圖必須惟一命名(不能給視圖取與別的視圖或表相同的名字)
二、對於能夠建立的視圖數目沒有限制
三、爲了建立視圖,必須具備足夠的訪問權限。這些限制一般由數據庫管理人員授予
四、視圖能夠嵌套,便可以利用從其餘視圖中檢索數據的查詢來構造一個視圖
五、ORDER BY能夠用在視圖中,但若是從該視圖檢索數據的SELECT語句中也含有ORDER BY,那麼該視圖中的ORDER BY將被覆蓋
六、視圖中不能索引,也不能有關聯的觸發器或默認值
七、視圖能夠和表一塊兒使用。例如,編寫一條聯結表和視圖的SELECT語句。
--使用視圖
視圖的建立:
一、視圖用CREATE VIEW語句來建立
二、使用SHOW CREATE VIEW viewname;來查看建立視圖的語句
三、用DROP刪除視圖,能夠先用DROP再用CREATE,也能夠直接用CREATE OR REPLACE VIEW。若是要更新的視圖不存在,則第2條更新語句會建立一個視圖;若是要更新的視圖存在,則第2條更新語句會替換原有視圖。
--利用視圖簡化複雜的聯結
視圖最多見的應用之一就是隱藏複雜的SQL,這一般會涉及到聯結。
CREATE VIEW productcustomers AS SELECT cust_name, cust_contact, prod_id FROM customers, orders, orderitems WHERE customer.cust_id = orders.cust_id AND orderitems.order_num = orders.order_num;
ps:建立可重用的視圖:建立不受特定數據限制的視圖是一種好辦法。
--用視圖從新格式化檢索出的數據
SELECT Concat(RTrim(vend_name), '(', RTrim(vend_country), ')') AS vend_title FROM vendors ORDER BY vend_name;
-------------------------------------------------------------------
CREATE VIEW vendorlocations AS
SELECT Concat(RTrim(vend_name), '(', RTrim(vend_country), ')')
AS vend_title
FROM vendors
ORDER BY vend_name;
--用視圖過濾不想要的數據
視圖對於應用普通的WHERE子句也頗有用,過濾掉一些不用的字段。
ps:WHERE子句與WHERE子句:若是從視圖檢索數據時使用了一條WHERE子句,則兩組子句(一組在視圖中,另外一組是傳遞給視圖的)將自動組合。
--使用視圖與計算字段
SELECT prod_id, quantity, item_price, quantity * item_price AS expanded_price FROM orderitems WHERE order_num = 20005;
--更新視圖
迄今爲止的全部視圖都是和SELECT語句使用的。然而,視圖的數據可否更新?答案視狀況而定。
一般視圖是可更新的(即,能夠對它們使用INSERT、UPDATE和DELET)。更新一個視圖將更新其基表(能夠回憶一下,視圖自己沒有數據)。若是你對視圖增長或刪除行,其實是對其基表增長或刪除行。
可是,並不是全部的視圖都是可更新的。基本能夠說,若是MySQL不能正確地肯定被更新的基數據,則不容許更新(包括插入和刪除)。這實際上意味着,若是視圖定義中有如下操做,則不能進行視圖的更新:
一、分組(使用GROUP BY和HAVING)
二、聯結
三、子查詢
四、並
五、彙集函數(Min()、Count()、Sum()等)
六、DISTINCT
七、導出(計算)列
要記住視圖主要是用於數據檢索。
ps:可能的變更:將來的MySQL極可能會取消某些限制
將視圖用於檢索:通常,應該將視圖用於檢索(SELECT語句)而不用於更新(INSERtT、UPDATE和DELETE)
----使用存儲過程
--存儲過程
迄今位置,使用的大多數SQL語句都是針對一個或多個表的單條語句。並不是全部操做都這麼簡單,常常會有一個完整的操做須要多條語句才能完成。
單獨編寫每條語句,並根據結果有條件地執行另外的語句。在每次須要這個處理時(以及每一個須要它的應用中)都必須作這些工做。
能夠建立存儲過程。存儲過程簡單來講,就是爲之後的使用而保存的一條或多條MySQL語句的集合。可將其視爲批文件,雖然它的做用不只限於批處理。
--爲何要使用存儲過程
緣由以下:
一、經過把處理封裝在容易使用的單元中,簡單複雜的操做
二、因爲不要求反覆創建一系列處理步驟,這保證了數據的完整性。若是全部開發人員和應用程序都使用同一(試驗和測試)存儲過程,則所使用的代碼都是相同的。這一點的延伸就是防止錯誤。須要執行的步驟越多,出錯的可能性就越大。防止錯誤保證了數據的一致性。
三、簡化對變更的管理。若是表名、列名或業務邏輯(或別的內容)有變化。只須要更改存儲過程的代碼。使用它的人員甚至不須要知道這些變化。
這一點的延伸就是爲了安全性。經過存儲過程限制對基礎數據的訪問減小了數據訛誤(無心識的或別的緣由所致使的數據訛誤)的機會。
一、提升性能。由於適應存儲過程比使用單獨的SQL語句要快
二、存在一些只能用在單個請求中的MySQL元素和特性,存儲過程可使用它們來編寫功能更強更靈活的代碼。
總的來講,使用存儲過程的3個主要好處就是,簡單、安全和高性能。
通常來講,編寫存儲過程須要安全訪問權限。
ps:MySQL將編寫存儲過程的安全和訪問與執行存儲過程的安全和訪問區分開。即便你不能(或不想)編寫本身的存儲過程,也仍然能夠在適當的時候執行別的存儲過程。
--使用存儲過程
MySQL稱存儲過程的執行爲調用,所以MySQL執行存儲過程的語句爲CALL。CALL接受存儲過程的名字以及須要傳遞給它的任意參數。
----------執行叫作productpricing的存儲過程
CALL productpricing ( @pricelow, @pricehigh, @priceaverage );
--建立存儲過程
CREATE PROCEDURE productpricing() BEGIN SELECT Avg(prod_price) AS priceaverage FROM products; END
BEGIN和END是用來限定存儲過程體,過程僅是簡單的SELECT語句。
在MySQL處理這段代碼時,它建立一個新的存儲過程product-pricing。沒有返回數據,由於這段代碼並未調用存儲過程,這裏知識爲了之後使用而建立。
ps:MySQL命令行客戶機的分隔符:若是你使用的是MySQL命令行使用程序,應該仔細閱讀此說明。
默認的MySQL語句分隔符爲;(正如你已經在迄今爲止所使用的MySQL語句中所看到的那樣)。MySQL命令行實用程序也使用;做爲語句分隔符。若是命令行實用程序要解釋存儲過程自身內的;字符,則它們最終不會成爲存儲過程的成分,這會使存儲過程當中的SQL出現語法錯誤。
解決辦法是臨時更改命令行使用程序的語句分隔符,以下所示:
DELIMITER // CREATE PROCEDURE productpricing() BEGIN SELECT Avg(prod_price) AS priceaverage FROM products; END //
DELIMITER;
其中,DELIMITER //告訴命令行實用程序使用 // 做爲新的語句結束分隔符,能夠看到標誌存儲過程結束的END定義爲END //而不是END;。這樣,存儲過程體內的;仍然保持不動,而且正確地傳遞給數據庫引擎。最後,爲恢復爲原來的語句分隔符,可以使用DELIMITER ;。
除 \ 符號外,任何字符均可以用做語句分隔符。
使用存儲過程關鍵字是CALL
CALL productpricing();
--刪除存儲過程
存儲過程建立以後,被保存在服務器上以供使用,直至被刪除。刪除命令從服務器中刪除存儲過程。
DROP PROCEDURE productpricing;
ps:僅當存在時刪除:若是指定的國策灰姑娘不存在,則DROP PROCEDURE將產生一個錯誤。當過程存在想刪除它時(若是過程不存在也產生)可以使用DROP PROCEDURE IF EXISTS。
--使用參數
存儲通常不顯示結果,而是把結果返回給你指定的變量。
變量(variable):內存中一個特定的位置,用來臨時存儲過程。
如下時productpricing的修改版本(若是不先刪除此存儲過程,則不能再次建立它):
CREATE PROCEDURE productpricing( OUT pl DECIMAL(8,2), OUT ph DECIMAL(8,2), OUT pa DECIMAL(8,2) ) BEGIN SELECT Min(prod_price) INTO pl FROM products; SELECT Max(prod_price) INTO ph FROM products; SELECT Avg(prod_price) INTO pa FROM products; END;
ps:參數的數據類型:存儲過程的參數容許的數據類型與表中使用的數據類型相同。
注意,記錄集不是容許的類型,所以,不能經過一個參數返回多個行和列。這就是前面的例子爲何要使用3個參數的緣由。
爲調用此修改過的存儲過程,必須指定3個變量名:
CALL productpricing( @pricelow, @pricehigh, @priceaverage ); ---------------------------------------- SELECT @priceaverage; ---------------------------------------- SELECT @pricelow, @pricehigh, @priceaverage;
變量名:全部MySQL變量都必須以@開始
----------------使用IN和OUT參數 CREATE PROCEDRUE ordertotal( IN onumber INT, OUT ototal DECIMAL(8,2) ) BEGIN SELECT Sum(item_price * quantity) FROM orderitems WHERE order_num = onumber INTO ototal; END;
onumber定義爲IN,由於訂單號被傳入存儲過程。ototal定義爲OUT,由於要從存儲過程當中返回合計。SELECT語句使用這兩個參數,WHERE子句使用onumber選擇正確的行,INTO使用ototal存儲計算出來的合計。
爲調用這個新存儲過程,可使用如下語句:
CALL ordertotal(20005, @total);
--創建智能存儲過程
只有在存儲過程內包含業務規則和智能處理時,它們的威力才能真正顯現出來。
如下的demo演示下面幾個事情:
一、得到合計;
二、把營業稅有條件地添加到合計;
三、返回合計(帶或不帶稅)
create procedure ordertotal( in onumber int, in taxable boolean, out ototal decimal(8,2) )comment 'obtain order total , optionally adding tax' begin declare total decimal(8,2); declare taxrate int default 6; select sum(item_price * quantity) from orderitems where order_num = onumber into total if taxable then select total+(total/100*taxrate) into total; end if; select total into ototal; end;
DECLARE語句定義局部變量,要求指定變量名和數據類型,也支持可選的默認值。
ps:COMMENT關鍵字:不是必需的,但若是給出,將在SHOW PROCEDURE STATUS的結果中顯示。
--檢查存儲過程
爲顯示用來建立一個存儲過程的create語句,使用show create procedure語句;
show create procedure ordertotal;
ps:限制過程狀態結果:SHOW PROCEDURE STATUS列出全部存儲過程。爲限制其輸出,可以使用LIKE指定一個過濾模式,
例如:show procedure status like 'ordertotal'
----使用遊標
--遊標
MySQL5增長了對遊標的使用。
MySQL檢索操做返回一組稱爲結果集的行。這組返回的行都是與SQL語句相匹配的行(零行或者多行)。使用簡單的SELECT語句,例如,沒有辦法獲得第一行、下一行或前10行,也不存在每次一行地處理全部行的簡單方法(相對於成批地處理它們)。
有時,須要在檢索出來的行中前進或後退一行或多行。這就是使用遊標的緣由。遊標(cursor)是一個存儲在MySQL服務器上的數據庫查詢,它不是一條select語句,而是被該語句檢索出來的結果集。在存儲了遊標以後,應用程序能夠根據須要滾動或瀏覽器中的數據。
遊標主要用於交互式應用,其中用戶須要滾動屏幕上的數據,並對數據進行瀏覽或作出更改。
ps:只能用於存儲過程:不像多數DBMS,MySQL遊標只能用於存儲過程(和函數)。
--使用遊標
使用遊標涉及幾個明確的步驟:
一、在可以使用遊標前,必須聲明(定義)它。這個過程實際上沒有檢索數據,它只是定義要使用的select語句。
二、一旦聲明後,必須打開遊標以供使用。這個過程用前面定義的select語句把數據實際檢索出來。
三、對於填有數據的遊標,根據須要取出(檢索)各行。
四、在結束遊標使用時,必須關閉遊標。
--建立遊標
遊標用DECLARE語句建立。DECLARE命名遊標,並定義相應的SELECT語句,根據須要帶WHERE和其餘子句。例如,下面的語句定義了名爲ordernumbers的遊標,使用了能夠檢索全部訂單的SELECT語句。
CREATE PROCEDURE processorders() BEGIN DECLARE ordernumbers CURSOR FOR SELECT order_num FROM orders; END;
--打開和關閉遊標
遊標用OPEN CURSOR語句來打開。。
OPEN ordernumbers;
關閉用CLOSE CURSOR,close釋放遊標使用的全部內部內存和資源,所以在每一個遊標再也不須要時都用改關閉。
CLOSE ordernumbers;
ps:隱含關閉:若是你不明確關閉遊標,MySQL將會在到達END語句時自動關閉它。
--使用遊標數據
在一個遊標被打開後,可使用FETCH語句分別訪問它的每一行。FETCH指定檢索什麼數據(所需的列),檢索出來的數據存儲在什麼地方。它還向前移動遊標中的內部行指針,使下一條(不重複讀取同一行)。
ps:DECLARE語句的次序:DECLARE語句的發佈存在特定的次序。用DECLARE語句定義的局部變量必須在定義任意遊標或句柄以前定義,而句柄必須在遊標以後定義。不遵照此順序將產生錯誤信息。
重複或循環?「除這裏使用的REPEAT語句外,MySQL還支持循環語句,它可用來重複執行代碼,直到使用LEAVE語句手動退出位置。一般REPEAT語句的語法使它更適合於對遊標進行循環。
-----使用觸發器
--觸發器
須要MySQL5:對觸發器的支持是在MySQL5中增長的。所以,本章內容適用於MySQL5或以後。
MySQL語句在須要時被執行,存儲過程也是如此。可是,若是你想要某條語句(或某些語句)在事件發生時自動執行,就須要使用觸發器。
觸發器時MySQL響應如下任意語句而自動執行的一條SQL語句(或位於BEGIN或END語句之間的一組語句):
DECLARE
INSERT
UPDATE
其餘MySQL語句不支持觸發器。
--建立觸發器
在建立觸發器時,須要給出4條信息:
一、惟一的觸發器名
二、觸發器關聯的表
三、觸發器應該響應的活動(DECLARE、INSERT或UODATE)
四、觸發器什麼時候執行(處理以前或以後)
ps:保持每一個數據庫的觸發器名惟一:在MySQL5中,觸發器名必須在每一個表中的惟一,但不是在每一個數據庫中惟一。這表示同一個數據庫中的兩個表可具備相同的名字的觸發器。這在其餘每一個數據庫觸發器名必須惟一的DBMS中是不容許的,並且之後的MySQL版本極可能會使命名規則更爲嚴格。所以,如今最好是在數據庫範圍捏使用惟一的觸發器名。
CREATE TRIGGER newproduct AFTER INSERT ON products FOR EACH ROW SELECT 'Product added'
ps:僅支持表:只有表才支持觸發器,試圖不支持(臨時表也不支持)
觸發器按每一個表每一個事件每次地定義,每一個表每一個事件每次只容許一個觸發器。所以,每一個表最多支持6個觸發器(每條INSERT、UPDATE和DELETE的以前和以後)。單一觸發器不能與多個事件或多個表關聯,因此,若是你須要一個對INSERT和UPDATE操做執行的觸發器,則應該定義兩個觸發器。
ps:觸發器失敗:若是BEFORE觸發器失敗,則MySQL將不執行請求的操做。此外,若是BEFORE觸發器或語句自己失敗,MySQL將不執行AFTER觸發器(若是有的話)
--刪除觸發器
使用DROP TRIGGER語句
DROP TRIGGER newproduct;
--使用觸發器
-INSERT觸發器
INSERT觸發器在INSERT語句執行以前或以後執行。須要知道如下幾點:
一、在INSERT觸發器代碼內,可引用一個名爲NEW的虛擬表,訪問被插入的行
二、在BEFORE INSERT觸發器內,NEW中的值也能夠被更新(容許更改被插入的值)
三、對於AUTO_INCREMENT列,NEW在INSERT執行以前包含0,在INSERT執行以後包含新的自動生成值
如下代碼,建立一個名爲neworder的觸發器,它按照AFTER INSERT ON orders執行。在插入一個新訂單到orders表時,MySQL生成一個新訂單號並保存到order_num中。觸發器從NEW.order_num取得這個值並返回它:
CREATE TRIGGER neworder AFTER INSERT ON orders FOR EACH ROW SELECT NEW.order_num;
ps:BEFORE或AFTER?:一般,將BEFORE用於數據驗證和淨化(目的是保證插入表中的數據確實是須要的數據)。本提示也適用於UPDATE觸發器。
--DELETE觸發器
DELETE觸發器在DELETE語句執行以前或以後執行。須要知道如下幾點:
一、在DELETE觸發器代碼內,你能夠引用一個名爲OLD的虛擬表,訪問被刪除的行
二、OLD中的值全都是隻讀的,不能更新
如下代碼,使用OLD保存將要被刪除的行到一個存檔表中:
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;
ps:多語句觸發器:正如所見,觸發器deleteorder使用BEGIN和END語句標記觸發器體。這在此例子中並非必需的,不過也沒有害處。使用BEGIN END塊的好處是觸發器能容納多條SQL語句(在BEGIN END塊中一條挨着一條)。
--UPDATE觸發器
UPDATE觸發器在UPDATE語句執行以前或以後執行。須要知道如下幾點:
一、在UPDATE觸發器代碼中,你能夠引用一個名爲OLD的虛擬表訪問之前的值,引用一個名爲NEW的虛擬表訪問更新的值
二、在BEFORE UPDATE觸發器中,NEW中的值可能也被更新(容許更改將要用於UPDATE語句的值)
三、OLD中的值全都是隻讀的,不能更新
下面的例子是保證周明縮寫老是大寫(無論UPDATE語句中給出的是大寫仍是小寫):
CREATE TRIGGER updatevendor BEFORE UPDATE ON vendors FOR EACH ROW SET NEW.vend_state = Upper(NEW.vend_stats);
--關於觸發器的進一步介紹
重點:
一、與其餘DBMS相比,MySQL5中支持的觸發器至關初級。將來的MySQL版本中有一些改進和加強觸發器支持的計劃
二、建立觸發器可能須要特殊的安全訪問權限,可是,觸發器的執行是自動的。若是INSERT、UPDATE或DELETE語句可以執行,則相關的觸發器也能執行
三、應該用觸發器來保證數據的一致性(大小寫、格式等)。在觸發器中執行這種類型的處理的有點是它老是進行這種處理,並且是透明地進行,與客戶機應用無關
四、觸發器的一種很是有意義的使用是建立審計跟蹤。使用觸發器,把更改(若是須要,甚至還有以前和以後的狀態)記錄到另外一個表很是容易
五、遺憾的是,MySQL觸發器中不支持CALL語句。這表示不能從觸發器內調用存儲過程。所需的存儲過程代碼須要複製到觸發器內。
----管理事務的處理
--事務處理
ps:並不是全部引擎都支持事務處理:MySQL支持幾種基本的數據庫引擎。並不是全部引擎都支持明確的事務處理管理。MyISAM和InnoDB是兩種最常使用的引擎。前者不支持明確的事務處理管理,然後者支持。若是你的應用中須要事務處理功能,則必定要使用正確的引擎類型。
事務處理(transaction processing)能夠用來維護數據庫的完整性,它保證成批的MySQL操做要麼徹底執行,要麼徹底不執行。
在使用事務和事務處理時,有幾個關鍵字會反覆出現。下面關於事務處理須要知道的幾個術語:
一、事務(transaction)指一組SQL語句
二、回退(rollbac)指撤銷指定SQL語句的過程
三、提交(commit)指將未存儲的SQL語句結果寫入數據庫表
四、保留點(savepoint)指事務處理中設置的臨時佔位符(placeholder),你能夠對它發佈回退(與回退整個事務處理不一樣)
--控制事務處理
管理事務處理的關鍵在於將SQL語句組分解爲邏輯塊,並明確規定數據什麼時候應該回退,什麼時候不該該回退。
MySQL使用下面的語句來標識事務的開始:
START TRANSACTION;
--使用ROLLBACK
MySQL使用ROLLBACK命令用來回退(撤銷)MySQL語句:
SELECT * FROM ordertotals; START TRANSACTION; DELETE FROM ordertotals; SELECT * FROM ordertotals; ROLLBACK; SELECT * FROM ordertotals;
根據上述例子可知,ROLLBACK只能在一個事務處理內使用(在執行一條START TRANSACTION命令以後)。
ps:哪些語句能夠回退:事務管理用來管理INSERT、UPDATE和DELETE語句。你不能回退SELECT語句(由於這麼作沒有意義)。你不能回退CREATE和DROP操做。事務處理塊中可使用這兩條語句,但若是你執行回退,它們不會被撤銷。
--使用COMMIT
通常的MySQL語句都是直接針對數據庫表執行和編寫的。這就是所謂的隱含提交(implict commit),即提交(寫或保存)操做是自動進行的。可是,在事務處理某塊中,提交不會隱含地進行。爲進行明確的提交,使用COMMIT語句,以下所示:
START TRANSACTION; DELETE FROM orderitems WHERE order_num = 20010; DELETE FROM orders WHERE order_num = 20010; COMMIT;
ps:隱含事務關閉:當COMMIT或ROLLBACK語句執行後,事務會自動關閉(未來的更改會隱含提交)
--使用保留點
爲了支持回退部分事務處理,必須能在事務處理塊中合適的位置放置佔位符。這樣,若是須要回退,能夠回退到某個佔位符。這些佔位符稱爲保留點。爲了建立佔位符,可以下使用SAVEPOINT語句:
SAVEPOINT delete1;
每一個佔位符都取標識它的惟一名字,以便在回退時,MySQL知道要回退到何處。爲了回退到本例給出的保留點,可以下進行:
ROLLBACK TO delete1;
ps:保留點越多越好:能夠在MySQL代碼中設置任意多的保留點,越多越好。由於保留點越多,你就越能按本身的意願靈活地進行回退。
釋放保留點:保留點在事務處理完成(執行一條ROLLBACK或COMMIT)後自動釋放。自MySQL5以來,也能夠用RELEASE SAVEPOINT明確地釋放保留點。
--更改默認的提交行爲
正如所述,默認的MySQL行爲是自動提交全部更改。換句話說,任什麼時候候你執行一條MySQL語句,該語句實際上都是針對表執行的,並且所作的更改當即生效。爲提示MySQL不自動提交更改,須要使用如下語句:
SET sutocommit=0;
autocommit標誌決定是都自動提交更改,無論有沒有COMMIT語句。設置autocommit爲0(假)只是MySQL不自動提交更改(直到autocommit被設置爲真爲止)。
ps:標誌爲鏈接專用:autocommit標誌是針對每一個鏈接而不是服務器的。
----全球化和本地化
--字符集和校對順序
數據庫表被用來存儲和檢索數據。不一樣的語言和字符集須要以不一樣的方式存儲和檢索。所以,MySQL須要使用不一樣的字符集(不一樣的字母和字符),適應不一樣的排序和檢索數據的方法。
重要屬於:
一、字符集爲字母和符號的集合
二、編碼爲某個字符集成員的內部表示
三、校對爲規定字符如何比較的指令
ps:校對很重要,由於不一樣的字符集排序方式不一樣,好比大小寫就是一種校對順序,還有就是法文或德文等字符,狀況更復雜,在不基於拉丁文的字符集(日文、希伯來語、俄文等)時,狀況就更爲複雜了。
--使用字符集和校對順序
MySQL支持衆多的字符集。爲查看所支持的字符集完整列表,使用如下語句:
--------這條語句顯示全部可用的字符集以及每一個字符集的描述和默認校對。
SHOW CHARACTER SET;
-------此語句顯示全部可用的校對,以及它們適用的字符集 SHOW COLLATION;
一般系統管理在安裝定義時定義一個默認的字符集和校對。此外,也能夠在建立數據庫時,指定默認的字符集和校對。爲了肯定所用的字符集和校對,可使用如下語句:
SHOW VARIABLES LIKE 'character%'; SHOW VARIABLES LIKE 'collation%';
實際上,字符集不多是服務器範圍(甚至是數據庫範圍)的設置。不一樣的表,甚至不一樣的列均可能須要不一樣的字符集,並且二者均可以在建立表時指定。
爲了給表指定字符集和校對,可以使用帶子句的CREATE TABLE,如下語句建立包含兩列的表,而且指定一個字符集和一個校對順序,這個例子中指定了CHARACTER SET和COLLATE。通常,MySQL以下肯定使用什麼樣子的字符集和校對。
一、若是指定CHARACTER SET和COLLATE二者,則使用這些值
二、若是隻指定CHARACTER SET,則使用此字符集及其默認的校對(若是SHOW CHARACTER SET的結果中所示)
三、若是既不指定CHARACTER SET,也不指定COLLATE,則使用數據庫默認。
CREATE TABLE mytable ( colum1 INT , colum2 VARCHAR(10) ) DEFAULT CHARACTER SET hebrew COLLATE hebrew_general_ci;
除了能指定字符集和校對的表範圍外,MySQL還容許對每一個列設置它們,以下所示:
CREATE TABLE mytable ( colum1 INT, colum2 VARCAHR(10), colum3 VARCAHR(10) CHARACTER SET latin1 COLLATE latin1_general_ci ) DEFAULT CHARACTER SET hebrew COLLATE hebrew_general_ci; -------這裏對整個表以及一個特定的列指定了CHARACTER SET和COLLATE
如前所述,校對在對用ORDER BY子句檢索出來的數據排序時起很重要的做用。若是你須要用與建立表時不一樣的校對順序排序特定的SELECT語句,能夠在SELECT語句自身中進行:
SELECT * FROM customers ORDER BY lastname, fistname COLLATE latin1_general_cs; ----此SELECT使用COLLATE指定一個備用的校對順序(在這個例子中,爲區分大小寫的校對)。這顯然會影響到結果排序的次序。
ps:臨時區分大小寫:上面的SELECT語句演示了在一般不區分大小寫的表上進行區分大小寫搜索的一種技術。固然,反過來也是能夠的。
SELECT的其餘COLLATE子句:除了這裏能夠看到的在ORDER BY子句中使用之外,COLLATE還能夠用於GROUP BY、HAVING、彙集函數、別名等。
**值得注意的是,若是絕對須要,串能夠在字符集之間進行轉換。爲此,使用Cast()或Convert()函數。
----安全管理
--訪問控制
MySQL服務器的安全基礎是:用戶應該對他們須要的數據具備適當的訪問權,既不能多也不能少。換句話說,用戶不能對過多的數據具備過多的訪問權。
考慮如下內容:
一、多數用戶只須要對錶進行讀和寫,但少數用戶甚至須要能建立和刪除表
二、某些用戶須要讀表,但可能不須要更新表
三、你可能想容許添加數據,但不容許他們刪除數據
四、某些用戶(管理員)可能須要處理用戶帳號的權限,但多數用戶不須要
五、你可能想讓用戶經過存儲過程訪問數據,但不容許他們直接訪問數據
六、你可能想根據用戶登陸的地點限制對某些功能的訪問
這些都只是例子,但有助於說明一個重要的事實,即你須要給用戶提供他們所需的訪問權,且僅提供他們所需的訪問權。這就是所謂的訪問控制,管理訪問控制須要建立和管理用戶帳號。
ps:使用MySQL Administrator:MySQL Administrator提供了一個圖形用戶界面,可用來管理用戶及帳戶權限。MySQL Administrator在內部利用本章介紹的語句,使用能交互地、方便地管理訪問控制。
咱們知道,爲了執行數據庫操做,須要登陸MySQL。MySQL建立一個名爲root的用戶帳戶,它對整個MySQL服務器具備徹底的控制。但在實際應用中,應該建立一系列的帳號,有的用於管理,有的供用戶使用,有的供開發人員使用。
ps:防止無心的錯誤:重要的是注意到,訪問控制的目的不只僅是防止用戶的惡意企圖。數據夢魘更爲常見的是無心識錯誤的結果,如打錯MySQL語句,在不適合的數據庫中操做或其餘一些用戶錯誤。經過保證用戶不能執行他們不該該執行的語句,訪問控制有助於避免這些狀況的發生。
不要使用root:應該嚴肅對待root登陸的使用。僅在絕對須要時使用它(或許在你不能登陸其餘管理帳號時使用)。不該該在平常的MySQL操做中使用root。
--管理用戶
MySQL用戶帳號和信息存儲在名爲mysql數據表中。通常不須要直接訪問mysql數據庫和表,但有時須要直接訪問。須要直接訪問它的時機之一是在須要得到全部用戶帳號列表時。爲此,可以使用如下代碼:
USE mysql; SELECT user FROM user;
ps:用多個客戶機進行試驗:試驗對用戶帳號和權限進行更改的最好辦法是打開多個數據庫客戶機(如mysql命令行實用程序的多個副本),一個做爲管理登陸,其餘做爲被測試的用戶登陸。
--建立用戶帳號
爲建立一個新用戶帳號,使用CREATE USER語句,以下所示:
CREATE USER ben IDENTIFIED BY 'p@$$w0rd'; ----CREATE USER建立一個新用戶帳號。在建立用戶帳號時不必定須要口令,不過這個例子用IDENTIFIED BY 'p@$$w0rd'給出了一個口令,若是你再次列出用戶帳號,將會在輸出中看到新帳號。
ps:指定散列口令:IDENTIFIED BY指定的口令爲純文本,MySQL將在保存到user表以前對其進行加密。爲了做爲散列值指定口令,使用IDENTIFIED BY PASSWORD.
使用GRANT或INSERT:GRANT語句也能夠建立用戶帳號,但通常來講CREATE USER是最清楚和最簡單的句子。此外,也能夠經過直接插入行到user表來增長用戶,不過爲安全起見,通常不建議這麼作。MySQL用來存儲用戶帳號信息的表(以及表模式等)極爲重要,對他們的任何毀壞均可能嚴重地傷害到MySQL服務器。所以,相對於直接處理來講,最好是用標記和函數來處理這些表。
爲從新命名一個用戶帳號,使用RENAME USER語句,以下所示:
RENAME USER ben TO bforta;
--刪除用戶帳號
爲了刪除一個用戶帳號(以及相關的權限),使用DROP USER語句,以下所示:
DROP USER bforta;
ps:MySQL 5以前:自MySQL 5以來,DROP USER刪除用戶帳號和全部相關的帳號和權限。在MySQL5之前,DROP USER只能用來刪除用戶帳號,不能刪除相關的 權限。所以,若是使用舊版本的MySQL,須要先用REVOKE刪除與帳號相關的權限,而後再用DROP USER刪除帳號。
--設置訪問權限
在建立用戶帳號後,必須接着分配訪問權限。新建立的用戶帳號沒有訪問權限。它們能登陸MySQL,但不能看到數據,不能執行任何數據庫操做。
爲看到賦予用戶帳號的權限,使用SHOW GRANT FOR,以下所示:
SHOW GRANT FOR bforta;
輸出結果顯示用戶bforta有一個權限USAGE ON *.*。USAGE表示根本沒有權限,因此此結果表示在任意數據庫和任意表上對任何東西沒有權限。
ps:用戶定義爲user@host:MySQL的權限用用戶名和主機名結合定義。若是不指定主機名,則使用默認的主機名%(授予用戶訪問權限而無論主機名)。
爲設置權限,使用GRANT語句。GRANT要求你至少給出如下信息:
一、要授予的權限
二、被授予訪問權限的數據庫或表
三、用戶名
如下給出GRANT的用法:
GRANT SELECT ON crashcourse.* TO bforta;
SHOW GRANT反應這個更改:
SHOW GRANT FOE beforta;
GRANT的反操做爲REVOKE,用它來撤銷特定的權限,舉個例子:
REVOKE SELECT ON crashcourse.* FROM bforta;
GRANT和REVOKE可在幾個層次上控制訪問權限:
一、整個服務器,使用GRANT ALL和REVOKE ALL
二、整個數據庫,使用ON database.*
三、特定的表,使用ON database.table
四、特定的列
五、特定的存儲過程
如下列出能夠授予或撤銷的每一個權限:
權限 | 說明 |
ALL | 除GRANT OPTION外的全部權限 |
ALTER ROUNTINE | 使用ALTER TABLE |
CREATE | 使用ALTER PROCEDURE和DROP PROCEDURE |
CREATE ROUTINE | 使用CREATE PROCEDURE |
CREATE TEMPORARY TABLES | 使用CREATE TEMPORARY TABLE |
CREATE USER | 使用CREATE USER、DROP USER、RENAME USER和REVOKE ALL PRIVILEGES |
CREATE VIEW | 使用CREATE VIEW |
DELETE | 使用DELETE |
DROP | 使用DROP TABLE |
EXECUTE | 使用CALL和存儲過程 |
FILE | 使用SELECT INTO OUTFILE和LOAD DATA INFILE |
GRANT OPTION | 使用GRANT和REVOKE |
INDEX | 使用CREATE INDEX和DROP INDEX |
INSERT | 使用INSERT |
LOCK TABLES | 使用LOCK TABLES |
PROCESS | 使用SHOW FULL PROCESSLIST |
RELOAD | 使用FLUSH |
REPLICATION CLIENT | 服務器位置的訪問 |
REPLICATION SLAVE | 由複製從屬使用 |
SELECT | 使用SELECT |
SHOW DATABASES | 使用SHOW DATABASES |
SHOW VIEW | 使用SHOW CREATE VIEW |
SHUT DOWN | 使用mysqladmin shutdown(用來關閉MySQL) |
SUPER | 使用CHANGE MASTER、KILL、LOGS、PURGE、MASTER和SER GLOBAL。還容許mysqladmin調試登陸 |
UPDATE | 使用UPDATE |
USAGE | 無訪問權限 |
使用GRANT和REVOKE,在結合上表列出權限,你能用戶能夠就你的寶貴數據作什麼事情和不能作什麼事情具備徹底的控制。
ps:將來的受權:在使用GRANT和REVOKE時,用戶帳號必須存在,但對所涉及的對象沒有這個要求。還容許管理員在建立數據庫的和表以前設計和實現安全措施。這樣作的反作用是,當某個數據庫或表被刪除時(用DROP語句),相關的訪問權限仍然存在,並且,若是未來從新建立該數據庫或表,這些權限仍然起做用。
簡化屢次受權:可經過列出各權限並用逗號分隔,將多條GRANT語句串在一塊兒,以下所示:
GRANT SELECT, INSERT, ON crashcourse.* TO bforeta;
--更改口令
爲了更改用戶口令,可以使用SET PASSWORD語句。新口令必須以下加密:
SELECT PASSWORD FOR bforta = Password('n3w p@$$w0rd');
-----分析:SET PASSWORD更新用戶口令。新口令必須傳遞到Password()函數進行加密。
SET PASSWORD還能夠用來設置你本身的口令:
SET PASSWORD = Password('n3w p@$$w0rd'); ----在不指定用戶名時,SET PASSWORD更新當前登陸用戶的口令。
----數據庫維護
--備份數據
解決普通的文件副本不必定老是有效的方案:
一、使用命令行使用程序mysqldump轉儲全部數據庫內容到某個外部文件。在進行常規備份前這個實用程序應該正常運行,以便能正確地備份轉儲文件
二、可用命令行實用程序mysqlhotcopy從一個數據庫複製全部數據(並不是全部數據庫引擎都支持這個實用程序)
三、可使用MySQL的BACKUP TABLE或SELECT INTO OUTFILE轉儲全部數據到某個外部文件。這兩條語句都接受將要建立的系統文件名,此係統文件必須不存在,不然會出錯。數據能夠用RESTORE TABLE來複原
ps:首先刷新未寫數據:爲了保證全部數據被寫道磁盤(包括索引數據),可能須要在進行備份前使用FLUSH TABLES語句。
--進行數據庫維護
MySQL提供了一系列的語句,能夠(應該)用來保證數據庫正確和正常運行。
-ANALYZE TABLE,用來檢查表鍵是否正確
ANALIZE TABLE orders;
-CHECK TABLE,用來針對許多問題對錶進行檢查。在MyISAM表上還對索引進行檢查。CHECK TABLE支持一系列的用於MyISAM表的方式。CHANGED檢查自最後一次檢查以來改動過的表。EXTENDED執行最完全的檢查,FAST只檢查未正常關閉的表,MEDIUM檢查全部被刪除的連接並進行鍵檢查,QUICK只進行快速掃描。以下所示,CHECK TABLE發現和修復問題:
CHECK TABLE orders, orderitems;
-若是MyISAM表訪問產生不正確和不一致的結果,可能須要用REPAIR TABLE來修復相應的表。這條語句不該該常用,若是須要常用,可能會有更大的問題要解決。
-若是從一個表中刪除大量數據,應該使用OPTIMIZE TABLE來收回全部的空間,從而優化表的性能。
--診斷啓動問題
服務器啓動問題一般在對MySQL配置或服務器自己進行更改時出現。MySQL在這個問題上發生時報告錯誤,但因爲多數MySQL服務器是做爲系統進程或服務自動啓動的,這些消息可能看不到。
在排除系統啓動問題時,首先應該儘可能用手動啓動服務器。MySQL服務器自身經過在命令行上執行mysqld啓動。下面是幾個重要的mysqld命令行選項:
一、--help顯示幫助———一個選項列表
二、--safe-mode裝載減去某些最佳配置的服務器
三、--verbose顯示全文本消息(爲得到更詳細的幫助消息與--help聯合使用)
四、--version顯示版本信息而後退出
--查看日誌文件
MySQL維護管理員依賴的一系列日誌文件。主要的日誌文件有如下幾種:
一、錯誤日誌。它包含啓動和關閉問題以及任意關鍵錯誤的細節。此日誌一般名爲hostname.err,位於data目錄中。此日誌名可用--log-error命令行選項更改。
二、查詢日誌。它記錄全部MySQL活動,在診斷問題時很是有用。此日誌文件可能會很快地變得很是大,所以不該該長期使用它。此日誌文件一般名爲hostname.log,位於data目錄中。此名字能夠用--log命令行選項更改。
三、二進制日誌。它記錄更新過數據(或者可能更新過的數據)的全部語句。此日誌一般名爲hostname-bin,位於data目錄內。此名字能夠用--log-bin命令行選項更改。注意,這個日誌文件是MySQL5中添加的,之前的MySQL版本中使用的是更新日誌。
四、緩慢查詢日誌。此日誌記錄執行緩慢的任何查詢。這個日誌在肯定數據庫何處須要優化頗有用。此日誌一般名爲hostname-slow.log,位於data目錄中。此名字能夠用--log-slo-queries命令行選項更改。
在使用日誌時,可用FLUSH LOGS語句來刷新和從新開始全部日誌文件。
----改善性能
一、首先,MySQL(與全部DBMS同樣)具備特定的硬件建議。在學習和研究MySQL時,使用任何舊的計算機做爲服務器均可以。但對用於生產的服務器來講,應該堅持遵循這些硬件建議
二、通常來講,關鍵的生產DBMS應該運行在本身的專用服務器上
三、MySQL是用一系列的默認設置預先設置的,這些設置開始一般是很好的。但過一段時間後你可能須要調整內存分配、緩衝區大小等。(爲查看當前設置,可以使用SHOW VARIABLES;和SHOW STATUS;)
四、MySQL是一個多用戶多線程的DBMS,換言之,它常常同時執行多個任務。若是這些任務中的某一個執行緩慢,則全部請求都會執行緩慢。若是你遇到顯著的性能不良,可以使用SHOW PROCESSLIST顯示全部活動進程(以及它們的線程ID和執行時間)。你還能夠用KILL命令終結某個特定的進程(使用這個命令須要做爲管理員登陸)
五、老是有不止一種方法編寫同一條SELECT語句。應該試驗聯結、並、子查詢等,找出最佳方法
六、使用EXPLAIN語句讓MySQL解釋它將如何執行一條SELECT語句
七、通常來講,存儲過程執行的比一條一條地執行其中的各條MySQL語句快
八、應該老是使用正確的數據類型
九、決不要檢索比須要還要多的數據。換言之,不要用SELECT *(除非你真正須要每一個列)
十、有的操做(包括INSERT)支持一個可選的DELAYED關鍵字,若是使用它,將把控制當即返回給調用程序,而且一旦有可能就實際執行該操做
十一、在導入數據時,應該關閉自動提交。你可能還想刪除索引(包括FULLTEXT索引),而後在導入完成後再重建它們
十二、必須索引數據庫表以改善數據檢索的性能。肯定索引什麼不是一件微不足道的任務,須要分析使用的SELECT語句以找出重複的WHERE和ORDER BY子句。若是一個簡單的WHERE子句返回結果所花的時間太長,則能夠判定其中使用的列(或幾個列)就是須要索引的對象
1三、你的SELECT語句中有一系列複雜的OR條件嗎?經過使用多條SELECT語句和鏈接它們的UNION語句,你能看到極大的性能的改進
1四、索引改善數據索引的性能,但損害數據插入、刪除和更行的性能。若是你有一些表,它們收集數據且不常常被搜索,則在有必要以前不要索引它們。(索引可根據須要添加和刪除)
1五、LIKE很慢。通常來講,最好使用FULLTEXT而不是LIKE
1六、數據庫是不斷變化的實體。一組優化良好的表一下子後可能就面目全非了。因爲表的使用和內容的更改,理想的優化和配置也會改變
17 、最重要的規則就是,每條規則在某些條件下都會被打破
ps:瀏覽文檔:http://dev.mysql.com/doc,更多的內容參考MySQL手冊
------------------------------------------------
本文章參考自《mysql必知必會》