mysql中以下正确的sql是_总结MySQL中SQL语法的使用
--where子句操作符:
where子句操作符
=
等于
<>
不等于(標準語法)
!=
不等于(非標準語法,可移植性差)
<
小于
<=
小于等于
>
大于
>=
大于等于
between
在指定的兩個值之間
IS NULL
空值檢查
IN(a, b)
在a與b之間
NOT
注意NOT在復雜語句中的應用,比如NOT IN(A, B),在簡單語句中,NOT沒有什么特別之處,但是在復雜語句中,顯得很重要
在MySQL中使用NOT對IN、BETWEEN和EXISTS子句取反,這個多數其他DBMS允許使用NOT對各種條件取反有很大差別
--通配符:%與_
%與_
%
%s
s%
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個聚集函數都可以如下使用:
1、對所有的行執行計算,指定ALL參數或不給參數(因為ALL是默認行為)
2、只包含不同的值,指定DISTINCT參數
如果指定列名,則DISTINCT只能用于COUNT(),按技術上來說,DISTINCT可以用于MAX()和MIN(),但是沒有意義
--組合聚集函數
意思就是select可以包含多個聚集函數
--分組數據
關鍵字GROUP BY
規定:
1、GROUP BY子句可以包含任意數目的列
2、如果在GROUP BY子句中嵌套了分組,數據將在最后規定的分組上進行匯總,換句話說,在建立分組時,指定的所有列都一起計算(所以不能從個別的列取回數據)
3、GROUP BY子句中列出的每個列都必須時檢索列或者有效的表達式(但不能是聚集函數),如果在select中使用表達式,則必須在GROUP BY子句中指定
相同的表達式,不能使用別名
4、除聚集計算語句外,select語句中的每個列都必須在GROUP BY子句中給出
5、如果分組列中具有NULL值,則NULL將作為一個分組返回。如果列中有多行NULL值,它們將分為一組
6、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和GOURP BY區別
ORDER BY
GROUP BY
排序產生的輸出
分組行。但輸出可能不是分組的順序
任意列都可以使用(甚至非選擇的列也可以使用)
只可能使用選擇列或表達式列,而且必須使用每個選擇列表達式
不一定需要
如果和聚集函數一起使用列(或表達式),則必須使用
PS:一般在使用GROUP BY子句時,應該也給出ORDER BY子句。這是保證數據正確排序的唯一方法,千萬不要依賴于GROUP BY排序數據
SELECT子句順序:
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), ')')ASvend_titleFROMvendorsORDER BY vend_name
----使用不同類型的聯結
內部聯結或等值聯結都是簡單聯結,其實還有其他聯結,分別是自聯結、自然聯結和外部聯結
--自聯結
用自聯結而不用子查詢:自然聯結通常作為外部語句用來替代從相同表中檢索數據時使用的子查詢語句。雖然最終的結果是一樣的,但有時候處理聯結遠比處理子查詢快得多。應該試一下兩種方法,以確定哪一種的性能更好。
selectprod_id,prod_name
fromproducts
where vend_id = (selectvend_id
fromproducts
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:事實上,迄今為止,我們建立的每個內部聯結都是自然聯結,很可能我們永遠都不會用到不是自然聯結的內部聯結
--外部聯結
聯結包含了那些在相關表中沒有關聯行的行,這種類型的聯結稱為外部聯結
selectcustomer.cust_id, orders.order_numfrom customers inner joinorderson customers.cust_id =orders.cust_id;selectcustomer.cust_id, orders.order_numfrom customers left joinorderson customers.cust_id = orders.cust_id;
PS:
1、沒有*=操作符,MySQL不支持簡化字符*=和=*的使用,這兩種操作符在其他DBMS中很流行
2、外部聯結的類型:存在兩種基本的外部聯結形式:左外部聯結和右外部聯結。它們之間的唯一差別是所關聯的表的順序不同。換句話說,左外部聯結可通過顛倒from或where子句中表的順序轉化為右外部聯結。因此,兩種類型的外部聯結可互換使用,而究竟使用哪一種純粹是根據方便而定。
--使用帶聚集函數的聯結
selectcustomer.cust_id,
customer.cust_name,count(orders.order_num) asnum_ordfromcustomerinner joinorderson customer.cust_id =orders.cust_idgroup by customer.cust_id
--使用聯結和聯結條件
要點:
1、注意所使用的聯結類型。一般我們使用內部聯結,但使用外部聯結也是有效的
2、保證使用正確的聯結條件,否則將返回不正確的數據
3、應該總是提供聯結條件,否則會得出笛卡爾積
4、在一個聯結中可以包含多個表,甚至對于每個聯結可以采取不同的聯結類型。雖然這樣做是合法的,一般也很有用,但應該在一起測試它們前,分別測試每個聯結。這將是故障排除更為簡單。
----組合查詢
--組合查詢
MySQL允許執行多個查詢(多條select語句),并將結果作為單位查詢結果集返回。這些組合查詢通常成為并(union)或復合查詢(compound query)。
有兩種基本情況,其中需要使用組合查詢:
1、在單個查詢中從不同的表返回類似結構的數據;
2、對單個表執行多個查詢,按單個查詢返回數據。
組合查詢和多個where條件:多數情況下,組合相同表的兩個查詢完成的工作與具有多個where子句條件的單條查詢完成的工作相同。換句話說,任何具有多個where子句的select語句都可以作為一個組合查詢給出,在以下段落中可以看到這一點。這兩種技術在不同的查詢中,性能也不同。因此,應該試一下兩種技術,以確定對特定的查詢哪一種性能更好。
--使用union創建組合查詢
給出每條select語句,在各條語句之間放上關鍵字union,下述寫法就是將兩個select查詢的東西合并在一起(3列)
selectvend_id, prod_id, prod_pricefromproductswhere prod_price <= 5
union
selectvend_id, prod_id, prod_pricefromproductswhere vend_id in (1001,1002)
簡單例子中,union比where復雜,但是遇到復雜的過濾條件,或者從多個表(而不是單個表)中檢索數據的情形,使用union可能會使處理更簡單。
--union規則
注意:
1、union必須由兩條以上的select語句組成,語句之間用關鍵字union分隔(因此,如果組合4條select語句,將要使用3個union關鍵字)
2、union中的每個查詢必須包含相同的列、表達式或聚集函數(不過各個列不需要以相同的次序列出)
3、列數據類型必須兼容:類型不必完全相同,但必須是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和正則表達式等搜索機制存在幾個重要的限制:
1、性能:通配符和正則表達式匹配通常要求MySQL嘗試匹配表中所有行(而且這些搜索極少使用)。因此,由于被搜索行數不斷增加,這些搜索可能非常耗時
2、明確控制:使用通配符和正則表達式匹配,很難(而且并不總是能)明確地控制匹配什么和不匹配什么。例如,指定一個詞必須匹配,一個詞必須不匹配,而一個詞僅在第一個詞確實匹配的情況下才可以匹配或者才可以不匹配
3、智能化的結果:雖然基于通配符和正則表達式的搜索提供了非常靈活的搜索,但它們都不能提供一種智能化的選擇結果的方法。例如,一個特殊詞的搜索將會返回多個包含該詞的所有行,而不區分包含單個匹配的行和包含多個匹配的行(按照可能時更好的匹配來排列它們)。類似,一個特殊詞的搜索將不會找出不包含該詞但包含其他相關詞的行。
所有這些限制以及更多的限制都可以用全文本搜索來解決。在使用全文本搜索時,MySQL不需要分別查看每個行,不需要分別分析和處理每個詞。MySQL創建指定列中各詞的一個索引,搜索可以針對這些詞進行。這樣,MySQL可以快速有效地決定哪些詞匹配(哪些行包含它們),哪些詞不匹配,它們匹配的頻率,等等。
--使用全文本搜索
為了進行全文本搜索,必須索引被搜索的列,而且要隨著數據的改變不斷地重新搜索。在對表列進行適當設計后,MySQL會自動進行所有的索引和重新索引。
在索引之后,select可與match()和against()一起使用以實際執行執行搜索。
-------演示FULLTEXT子句的使用
create tableproductnotes
(
note_idint not nullauto_increment,
prod_idchar(10) not null,
note_datedatetime 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對數據和索引進行兩遍掃描來完成搜索:
1、首先,進行一個基本的全文本搜索,找出與搜索條件匹配的所有行
2、其次,MySQL檢查這些匹配行并選擇所有有用的詞
3、再其次,MySQL再次進行全文本搜索,這次不僅使用原來的條件,而且還使用所有有用的詞。
查詢擴展增加了返回的行數,,但這樣做也增加了實際上并不想要的數目。
ps:行越多越好:表中的行越多(這些行中的文本就越多),使用查詢擴展返回的結果越好。
--布爾文本搜索
以布爾方式,可以提供關于如下內容的細節:
1、要匹配的詞
2、要排斥的詞(如果某行包含這個詞,則不反悔該行,即使它包含其他指定的詞也是如此)
3、排列提示(指定某些詞比其他詞更重要,更重要的詞等級更高)
4、表達式分組
5、另外一些內容
ps:即使沒有FULLTEXT索引也可以使用:布爾方式不同于迄今為止使用的全文本搜索語法的地方在于,即使沒有定義FULLTEXT索引,也可以使用它。但這是一種非常緩慢的操作(其性能將隨著數據量的增加而降低)
IN BOOLEAN MODE的行為差異
全文本布爾操作符
布爾操作符
說明
+
包含,詞必須存在
-
排除,詞必須不出現
>
包含,而且增加等級值
<
包含,且減少等級值
()
把詞組成子表達式(允許這些子表達式作為一個組被包含、排除、排列等)
~
取下一個詞的排序值
*
詞尾的通配符
""
定義一個短語(與單個詞的列表不一樣,它匹配整個短語以便包含或排除這個短語)
ps:排列而不排序:在布爾方式中,不按等級值降序排序返回的行
-全文本搜索的使用說明
1、在索引全文本數據時,短詞被忽略且從索引中排除。短語定義為那些具有3個或3個以下字符的詞(如果需要,這個數目可以更改)
2、MySQL帶有一個內建的非用詞(stopword)列表,這些詞在索引全文本數據時總是被忽略。如果需要,可以覆蓋這個列表
3、許多詞出現的頻率很高,搜索它們沒有用處(返回太多的結果)。因此,MySQL規定了一條50%規則,如果一個詞出現在50%以上的行中,則將它作為一個非用詞忽略。50%規則不用于IN BOOLEAN MODE
4、如果表中的行數少于3行,則全文本搜索不返回結果(因為每個詞或者不出現,或者至少出現在50%的行中)
5、忽略此中的單引號。例如,don't索引為dont
6、不具有詞分隔符(包括日語和漢語)的語言不能恰當地返回全文本搜索結果
7、僅在MyISAM數據庫引擎中支持全文本搜索
----插入數據
--數據插入
插入可以用幾種方式使用:
1、插入完整的行
2、插入行的一部分
3、插入多行
4、插入某些查詢的結果
插入及系統安全:可針對每個表或每個用戶,利用MySQL的安全機制機制禁止使用INSERT語句
--插入完整的行
insert intocustomersvalues (null,'LeeMichael','100 street','los angle',null,'USA');
-----------------------------------
insert intocustomers(
cust_name,
cust_addr,
cust_city,
cust_country)
values ('LeeMichael',
'100 street',
'los angle','USA');
ps:總是使用列的列表:一般不要使用沒有明確給出列的列表的INSERT語句。使用列的列表能使SQL代碼繼續發揮作用,即使表結構發生了變化。
仔細地給出值:不管使用哪種INSERT語法,都必須給出values的正確數目。如果不提供列名,則必須給每個表列提供一個值。如果提供列名,則必須對梅格列出的列給出一個值。如果不這樣,將產生一條錯誤信息,相應的行插入不成功。
省略列:如果表的定義允許,則可以在INSERT操作中省略某些列。省略的列必須滿足以下某個條件:
1、該列定義為允許null值(無值或空值)
2、在表定義中給出默認值。這表示如果不給出值,將使用默認值
如果對表中不允許null值且沒有默認值的列不給出值,則MySQL將產生一條錯誤消息,并且相應的行插入不成功。
提高整體性能:數據庫經常被多個客戶訪問,對處理什么請求以及用什么次序處理進行管理是MySQL的任務。INSERT操作可能很耗時(特別是有很多索引需要更新時),而且它可能降低等待處理的select語句的性能
如果數據檢索是最重要的(通常是這樣),則你可以通過在INSERT和INTO之間添加關鍵字LOW_PRIORITY,指示MySQL降低INSERT語句的優先級,如:INSERT LOW_PRIORITY INTO,這也適用于UPDATE和DELETE。
--插入多個行
insert intocustomers(
cust_name,
cust_addr,
cust_city,
cust_country)values('LeeMichael','100 street','los angle','USA');insert intocustomers(
cust_name,
cust_addr,
cust_city,
cust_country)values('LGQMichael','100 street','los angle','USA');
多個語句,用 ; 隔開
或者可以這樣(這樣寫可以提高性能):
insert intocustomers(
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 intocustomers (cust_id,
cust_contact,
cust_email,
cust_name,
cust_addr,
cust_city)selectcust_id,
cust_contact,
cust_email,
cust_name,
cust_addr,
cust_cityfrom custnew
ps:INSERT SELECT中的別名:為簡單起見,這個例子在INSERT和SELECT語句中使用了相同的列名。但是,不一定要求列名匹配。事實上,MySQL甚至不關心SELECT返回的列名。它使用的是列的位置,因此SELECT中的第一列(不管其列名)將用來填充表列中指定的第一列,第二列將用來填充表列中指定的第二個列,如此等等。這對于從使用不同列名的表中導入數據時非常有用的。
INSERT SELECT中SELECT語句中可以包含where子句以過濾插入的數據。
----更新和刪除數據
--更新數據
為了更新(修改)表中的數據,可使用UPDATE語句。可采用兩種方式使用UPDATE:
1、更新表中特定行
2、更新表總所有行
ps:不要省略WHERE子句:在使用UPDATE時一定要注意細心。因為稍不注意,就會更新表中所有行。
UPDATE與安全:可以限制和控制UPDATE語句的使用。
基本的UPDATE語句由3個部分組成,分別是:
1、要更新的表
2、列名和它們的新值
3、確定要更新行的過濾條件
updatecustomersset cust_email = 'lgq@163.com'
where cust_id = 1005;
ps: 在UPDATE語句中使用子查詢:UPDATE語句中可以使用子查詢,使得能用SELECT語句檢索出的數據更新列數據
IGNORE關鍵字:如果能用UPDATE語句更新多行,并且在更新這些行中的一行
--刪除數據
為了從一個表中刪除(去掉)數據,使用delete語句。分為兩種方式:
1、從表中刪除特定的行
2、從表中刪除所有行
ps:不要省略where子句:在使用delete時一定要注意細心。因為稍不注意,就會錯誤地刪除表中所有行。
delete與安全:可以限制和控制delete語句的使用
刪除表的內容而不是表:delete語句從表中刪除行,甚至是刪除表中所有行。但是,delete不是刪除表本身。
更快的刪除:如果想從表中刪除所有行,不要使用delete。可以使用TRUNCATE TABLE語句,它完成相同的工作,但速度更快(TRUNCATE實際是刪除原來的 表并不重新創建一個表,而不是逐行刪除表中的數據)
--更新和刪除的指導原則
許多SQL程序員使用UPDATE和DELETE時所遵循的習慣:
1、除非確實打算更新和刪除每一行,否則絕對不要使用不帶where子句的UPDATE和DELETE
2、保證每個表都有主鍵,盡可能想where子句那樣使用它(可以指定各主鍵、多個值或值的范圍)
3、在對UPDATE或DELETE語句使用where子句前,應該先用SELECT進行測試,保證它過濾的是正確的記錄,以防編寫的where子句不正確
4、使用強制實施引用完整性的數據庫,這樣MySQL將不允許刪除與其他相關聯的數據的行
ps:小心使用:MySQL沒有撤銷(undo)按鈕。應該非常小心地使用UPDATE和DELETE,否則你會發現自己更新或刪除了錯誤的數據。
----創建和操縱表
--創建表
方法:
1、使用具有交互式創建和管理表的工具
2、表也可以直接用MySQL語句操縱
--表創建基礎
1、新表的名字,在關鍵字create table之后給出
2、表列的名字和定義,用逗號分隔開
create tablecustomers
(
cust_idint not nullauto_increment,
cust_namechar(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 tableorderitems
(
order_numint not null,
order_itemint not null,
prod_idchar(10) not null,
quantityint not null default 1,
item_pricedecimal(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=語句很重要的原因。
引擎介紹:
1、InnoDB是一個可靠的事務處理引擎,它不支持全文本搜索
2、MEMORY在功能等同于MyISAM,但由于數據存儲在內存(不是磁盤)中,速度很快(特別適用于臨時表)
3、NyISAM是一個性能極高的引擎,它支持全文本搜索,但不支持事務處理。
引擎類型可以混用。
外鍵不能跨引擎:混用引擎類型有一個大缺陷。外鍵(用于強制實施引用完整性)不能跨引擎,即使用一個引擎的表不能引用具有使用不同引擎的表的外鍵。
--更新表
為更新表定義,可使用ALTER TABLE語句。但是,在理想狀態下,當表中存儲數據之后,該表就不應該再被更新。在表的設計過程中需要花費大量時間來考慮,以便后期不對該表進行大的改動。
為了使用ALTER TABLE更改表結構,必須給出下面的信息:
1、在ALTER TABLE之后給出要更改的表名(該表必須存在,否則將出錯)
2、所作更改的列表
ALTER TABLEvendorsADD vend_phone char(20);--------------------------------------
ALTER TABLEvendorsDROP COLUMN vend_phone;
復雜表結構更改一般需要手動刪除過程,它設計以下步驟:
1、用新的列布局創建一個新表
2、使用INSERT SELECT語句從舊表復制數據到新表,如有必要可使用轉換函數和計算字段
3、檢驗包含所需數據的新表
4、重命名舊表(如果確定,可以刪除它)
5、用舊表原來的名字重命名新表
6、根據需要,重新創建觸發器、存儲過程、索引和外鍵
ps:小心使用ALTER TABLE:使用ALTER TABLE要極為小心,應該在進行改動前做一個完整的備份(模式和數據的備份)。數據庫表的更改不能撤銷,如果增加了不需要的列,可能不能刪除它們。類似的,如果刪除了不應該刪除的列,可能會丟失該列中的所有數據。
--刪除表
DROP TABLE customers;
--重命名表
使用RENAME TABLE語句可以重命名一個表
RENAME TABLE backup_customers TOcustomers,
backup_vendorsTO vendors;
----使用視圖
視圖的一些常見應用:
1、重用SQL語句
2、簡單復雜的SQL操作。在編寫查詢后,可以方便地重用它而不必知道它的基本查詢細節
3、使用表的組成部分而不是整個表
4、保護數據。可以給用戶授予表的特定部分的訪問權限而不是整個表的訪問權限
5、更改數據格式和表示。視圖可返回與底層表的表示和格式不同的數據。
重點:視圖僅僅是用來查看存儲在別處的數據的一種設施。視圖本身不包含數據,因此它們返回的數據是從其他表中檢索出來的。在添加或更改這些表中的數據時,視圖將返回改變過的數據。
ps:性能問題:因為視圖不包含數據,所以每次使用視圖時,都必須處理查詢執行時所需的任一個檢索。如果你用多個聯結和過濾創建一個復雜的視圖或者嵌套了視圖,可能會發現性能下降的很厲害。因此,在部署使用了大量視圖的應用前,應該進行測試。
--視圖的規則和限制
1、與表一樣,視圖必須唯一命名(不能給視圖取與別的視圖或表相同的名字)
2、對于可以創建的視圖數目沒有限制
3、為了創建視圖,必須具有足夠的訪問權限。這些限制通常由數據庫管理人員授予
4、視圖可以嵌套,即可以利用從其他視圖中檢索數據的查詢來構造一個視圖
5、ORDER BY可以用在視圖中,但如果從該視圖檢索數據的SELECT語句中也含有ORDER BY,那么該視圖中的ORDER BY將被覆蓋
6、視圖中不能索引,也不能有關聯的觸發器或默認值
7、視圖可以和表一起使用。例如,編寫一條聯結表和視圖的SELECT語句。
--使用視圖
視圖的創建:
1、視圖用CREATE VIEW語句來創建
2、使用SHOW CREATE VIEW viewname;來查看創建視圖的語句
3、用DROP刪除視圖,可以先用DROP再用CREATE,也可以直接用CREATE OR REPLACE VIEW。如果要更新的視圖不存在,則第2條更新語句會創建一個視圖;如果要更新的視圖存在,則第2條更新語句會替換原有視圖。
--利用視圖簡化復雜的聯結
視圖最常見的應用之一就是隱藏復雜的SQL,這通常會涉及到聯結。
CREATE VIEW productcustomers AS
SELECTcust_name, cust_contact, prod_idFROMcustomers, orders, orderitemsWHERE customer.cust_id =orders.cust_idAND orderitems.order_num = orders.order_num;
ps:創建可重用的視圖:創建不受特定數據限制的視圖是一種好辦法。
--用視圖重新格式化檢索出的數據
SELECT Concat(RTrim(vend_name), '(', RTrim(vend_country), ')')ASvend_titleFROMvendorsORDER 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子句,則兩組子句(一組在視圖中,另一組是傳遞給視圖的)將自動組合。
--使用視圖與計算字段
SELECTprod_id, quantity, item_price,
quantity* item_price ASexpanded_priceFROMorderitemsWHERE order_num = 20005;
--更新視圖
迄今為止的所有視圖都是和SELECT語句使用的。然而,視圖的數據能否更新?答案視情況而定。
通常視圖是可更新的(即,可以對它們使用INSERT、UPDATE和DELET)。更新一個視圖將更新其基表(可以回憶一下,視圖本身沒有數據)。如果你對視圖增加或刪除行,實際上是對其基表增加或刪除行。
但是,并非所有的視圖都是可更新的。基本可以說,如果MySQL不能正確地確定被更新的基數據,則不允許更新(包括插入和刪除)。這實際上意味著,如果視圖定義中有以下操作,則不能進行視圖的更新:
1、分組(使用GROUP BY和HAVING)
2、聯結
3、子查詢
4、并
5、聚集函數(Min()、Count()、Sum()等)
6、DISTINCT
7、導出(計算)列
要記住視圖主要是用于數據檢索。
ps:可能的變動:未來的MySQL很可能會取消某些限制
將視圖用于檢索:一般,應該將視圖用于檢索(SELECT語句)而不用于更新(INSERtT、UPDATE和DELETE)
----使用存儲過程
--存儲過程
迄今位置,使用的大多數SQL語句都是針對一個或多個表的單條語句。并非所有操作都這么簡單,經常會有一個完整的操作需要多條語句才能完成。
單獨編寫每條語句,并根據結果有條件地執行另外的語句。在每次需要這個處理時(以及每個需要它的應用中)都必須做這些工作。
可以創建存儲過程。存儲過程簡單來說,就是為以后的使用而保存的一條或多條MySQL語句的集合。可將其視為批文件,雖然它的作用不僅限于批處理。
--為什么要使用存儲過程
原因如下:
1、通過把處理封裝在容易使用的單元中,簡單復雜的操作
2、由于不要求反復建立一系列處理步驟,這保證了數據的完整性。如果所有開發人員和應用程序都使用同一(試驗和測試)存儲過程,則所使用的代碼都是相同的。這一點的延伸就是防止錯誤。需要執行的步驟越多,出錯的可能性就越大。防止錯誤保證了數據的一致性。
3、簡化對變動的管理。如果表名、列名或業務邏輯(或別的內容)有變化。只需要更改存儲過程的代碼。使用它的人員甚至不需要知道這些變化。
這一點的延伸就是為了安全性。通過存儲過程限制對基礎數據的訪問減少了數據訛誤(無意識的或別的原因所導致的數據訛誤)的機會。
1、提高性能。因為適應存儲過程比使用單獨的SQL語句要快
2、存在一些只能用在單個請求中的MySQL元素和特性,存儲過程可以使用它們來編寫功能更強更靈活的代碼。
總的來說,使用存儲過程的3個主要好處就是,簡單、安全和高性能。
一般來說,編寫存儲過程需要安全訪問權限。
ps:MySQL將編寫存儲過程的安全和訪問與執行存儲過程的安全和訪問區分開。即使你不能(或不想)編寫自己的存儲過程,也仍然可以在適當的時候執行別的存儲過程。
--使用存儲過程
MySQL稱存儲過程的執行為調用,因此MySQL執行存儲過程的語句為CALL。CALL接受存儲過程的名字以及需要傳遞給它的任意參數。
----------執行叫做productpricing的存儲過程
CALL productpricing
(@pricelow,@pricehigh,@priceaverage);
--創建存儲過程
CREATE PROCEDUREproductpricing()BEGIN
SELECT Avg(prod_price) ASpriceaverageFROMproducts;END
BEGIN和END是用來限定存儲過程體,過程僅是簡單的SELECT語句。
在MySQL處理這段代碼時,它創建一個新的存儲過程product-pricing。沒有返回數據,因為這段代碼并未調用存儲過程,這里知識為了以后使用而創建。
ps:MySQL命令行客戶機的分隔符:如果你使用的是MySQL命令行使用程序,應該仔細閱讀此說明。
默認的MySQL語句分隔符為;(正如你已經在迄今為止所使用的MySQL語句中所看到的那樣)。MySQL命令行實用程序也使用;作為語句分隔符。如果命令行實用程序要解釋存儲過程自身內的;字符,則它們最終不會成為存儲過程的成分,這會使存儲過程中的SQL出現語法錯誤。
解決辦法是臨時更改命令行使用程序的語句分隔符,如下所示:
DELIMITER //
CREATE PROCEDUREproductpricing()BEGIN
SELECT Avg(prod_price) ASpriceaverageFROMproducts;END //
DELIMITER;
其中,DELIMITER //告訴命令行實用程序使用 // 作為新的語句結束分隔符,可以看到標志存儲過程結束的END定義為END //而不是END;。這樣,存儲過程體內的;仍然保持不動,并且正確地傳遞給數據庫引擎。最后,為恢復為原來的語句分隔符,可使用DELIMITER? ;。
除 \ 符號外,任何字符都可以用作語句分隔符。
使用存儲過程關鍵字是CALL
CALL productpricing();
--刪除存儲過程
存儲過程創建之后,被保存在服務器上以供使用,直至被刪除。刪除命令從服務器中刪除存儲過程。
DROP PROCEDURE productpricing;
ps:僅當存在時刪除:如果指定的國策灰姑娘不存在,則DROP PROCEDURE將產生一個錯誤。當過程存在想刪除它時(如果過程不存在也產生)可使用DROP PROCEDURE IF EXISTS。
--使用參數
存儲一般不顯示結果,而是把結果返回給你指定的變量。
變量(variable):內存中一個特定的位置,用來臨時存儲過程。
以下時productpricing的修改版本(如果不先刪除此存儲過程,則不能再次創建它):
CREATE PROCEDUREproductpricing(
OUT plDECIMAL(8,2),
OUT phDECIMAL(8,2),
OUT paDECIMAL(8,2)
)BEGIN
SELECT Min(prod_price)INTOplFROMproducts;SELECT Max(prod_price)INTOphFROMproducts;SELECT Avg(prod_price)INTOpaFROMproducts;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演示下面幾個事情:
1、獲得合計;
2、把營業稅有條件地添加到合計;
3、返回合計(帶或不帶稅)
create procedureordertotal(in onumber int,intaxable boolean,
out ototaldecimal(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)fromorderitemswhere order_num =onumberintototalif taxable then
select total+(total/100*taxrate) intototal;end if;select total intoototal;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游標只能用于存儲過程(和函數)。
--使用游標
使用游標涉及幾個明確的步驟:
1、在能夠使用游標前,必須聲明(定義)它。這個過程實際上沒有檢索數據,它只是定義要使用的select語句。
2、一旦聲明后,必須打開游標以供使用。這個過程用前面定義的select語句把數據實際檢索出來。
3、對于填有數據的游標,根據需要取出(檢索)各行。
4、在結束游標使用時,必須關閉游標。
--創建游標
游標用DECLARE語句創建。DECLARE命名游標,并定義相應的SELECT語句,根據需要帶WHERE和其他子句。例如,下面的語句定義了名為ordernumbers的游標,使用了可以檢索所有訂單的SELECT語句。
CREATE PROCEDUREprocessorders()BEGIN
DECLARE ordernumbers CURSOR
FOR
SELECT order_num FROMorders;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條信息:
1、唯一的觸發器名
2、觸發器關聯的表
3、觸發器應該響應的活動(DECLARE、INSERT或UODATE)
4、觸發器何時執行(處理之前或之后)
ps:保持每個數據庫的觸發器名唯一:在MySQL5中,觸發器名必須在每個表中的唯一,但不是在每個數據庫中唯一。這表示同一個數據庫中的兩個表可具有相同的名字的觸發器。這在其他每個數據庫觸發器名必須唯一的DBMS中是不允許的,而且以后的MySQL版本很可能會使命名規則更為嚴格。因此,現在最好是在數據庫范圍捏使用唯一的觸發器名。
CREATE TRIGGER newproduct AFTER INSERT ONproductsFOR 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語句執行之前或之后執行。需要知道以下幾點:
1、在INSERT觸發器代碼內,可引用一個名為NEW的虛擬表,訪問被插入的行
2、在BEFORE INSERT觸發器內,NEW中的值也可以被更新(允許更改被插入的值)
3、對于AUTO_INCREMENT列,NEW在INSERT執行之前包含0,在INSERT執行之后包含新的自動生成值
以下代碼,創建一個名為neworder的觸發器,它按照AFTER INSERT ON orders執行。在插入一個新訂單到orders表時,MySQL生成一個新訂單號并保存到order_num中。觸發器從NEW.order_num取得這個值并返回它:
CREATE TRIGGER neworder AFTER INSERT ONordersFOR EACH ROW SELECT NEW.order_num;
ps:BEFORE或AFTER?:通常,將BEFORE用于數據驗證和凈化(目的是保證插入表中的數據確實是需要的數據)。本提示也適用于UPDATE觸發器。
--DELETE觸發器
DELETE觸發器在DELETE語句執行之前或之后執行。需要知道以下幾點:
1、在DELETE觸發器代碼內,你可以引用一個名為OLD的虛擬表,訪問被刪除的行
2、OLD中的值全都是只讀的,不能更新
以下代碼,使用OLD保存將要被刪除的行到一個存檔表中:
CREATE TRIGGER deleteorder BEFORE DELETE ONordersFOREACH ROWBEGIN
INSERT INTOarchive_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語句執行之前或之后執行。需要知道以下幾點:
1、在UPDATE觸發器代碼中,你可以引用一個名為OLD的虛擬表訪問以前的值,引用一個名為NEW的虛擬表訪問更新的值
2、在BEFORE UPDATE觸發器中,NEW中的值可能也被更新(允許更改將要用于UPDATE語句的值)
3、OLD中的值全都是只讀的,不能更新
下面的例子是保證周明縮寫總是大寫(不管UPDATE語句中給出的是大寫還是小寫):
CREATE TRIGGER updatevendor BEFORE UPDATE ONvendorsFOR EACH ROW SET NEW.vend_state = Upper(NEW.vend_stats);
--關于觸發器的進一步介紹
重點:
1、與其他DBMS相比,MySQL5中支持的觸發器相當初級。未來的MySQL版本中有一些改進和增強觸發器支持的計劃
2、創建觸發器可能需要特殊的安全訪問權限,但是,觸發器的執行是自動的。如果INSERT、UPDATE或DELETE語句能夠執行,則相關的觸發器也能執行
3、應該用觸發器來保證數據的一致性(大小寫、格式等)。在觸發器中執行這種類型的處理的有點是它總是進行這種處理,而且是透明地進行,與客戶機應用無關
4、觸發器的一種非常有意義的使用是創建審計跟蹤。使用觸發器,把更改(如果需要,甚至還有之前和之后的狀態)記錄到另一個表非常容易
5、遺憾的是,MySQL觸發器中不支持CALL語句。這表示不能從觸發器內調用存儲過程。所需的存儲過程代碼需要復制到觸發器內。
----管理事務的處理
--事務處理
ps:并非所有引擎都支持事務處理:MySQL支持幾種基本的數據庫引擎。并非所有引擎都支持明確的事務處理管理。MyISAM和InnoDB是兩種最常使用的引擎。前者不支持明確的事務處理管理,而后者支持。如果你的應用中需要事務處理功能,則一定要使用正確的引擎類型。
事務處理(transaction processing)可以用來維護數據庫的完整性,它保證成批的MySQL操作要么完全執行,要么完全不執行。
在使用事務和事務處理時,有幾個關鍵字會反復出現。下面關于事務處理需要知道的幾個術語:
1、事務(transaction)指一組SQL語句
2、回退(rollbac)指撤銷指定SQL語句的過程
3、提交(commit)指將未存儲的SQL語句結果寫入數據庫表
4、保留點(savepoint)指事務處理中設置的臨時占位符(placeholder),你可以對它發布回退(與回退整個事務處理不同)
--控制事務處理
管理事務處理的關鍵在于將SQL語句組分解為邏輯塊,并明確規定數據何時應該回退,何時不應該回退。
MySQL使用下面的語句來標識事務的開始:
START TRANSACTION;
--使用ROLLBACK
MySQL使用ROLLBACK命令用來回退(撤銷)MySQL語句:
SELECT * FROMordertotals;
STARTTRANSACTION;DELETE FROMordertotals;SELECT * FROMordertotals;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需要使用不同的字符集(不同的字母和字符),適應不同的排序和檢索數據的方法。
重要屬于:
1、字符集為字母和符號的集合
2、編碼為某個字符集成員的內部表示
3、校對為規定字符如何比較的指令
ps:校對很重要,因為不同的字符集排序方式不同,比如大小寫就是一種校對順序,還有就是法文或德文等字符,情況更復雜,在不基于拉丁文的字符集(日文、希伯來語、俄文等)時,情況就更為復雜了。
--使用字符集和校對順序
MySQL支持眾多的字符集。為查看所支持的字符集完整列表,使用以下語句:
--------這條語句顯示所有可用的字符集以及每個字符集的描述和默認校對。
SHOW CHARACTER SET;
-------此語句顯示所有可用的校對,以及它們適用的字符集
SHOW COLLATION;
通常系統管理在安裝定義時定義一個默認的字符集和校對。此外,也可以在創建數據庫時,指定默認的字符集和校對。為了確定所用的字符集和校對,可以使用以下語句:
SHOW VARIABLES LIKE 'character%';
SHOW VARIABLESLIKE 'collation%';
實際上,字符集很少是服務器范圍(甚至是數據庫范圍)的設置。不同的表,甚至不同的列都可能需要不同的字符集,而且兩者都可以在創建表時指定。
為了給表指定字符集和校對,可使用帶子句的CREATE TABLE,以下語句創建包含兩列的表,并且指定一個字符集和一個校對順序,這個例子中指定了CHARACTER SET和COLLATE。一般,MySQL如下確定使用什么樣子的字符集和校對。
1、如果指定CHARACTER SET和COLLATE兩者,則使用這些值
2、如果只指定CHARACTER SET,則使用此字符集及其默認的校對(如果SHOW CHARACTER SET的結果中所示)
3、如果既不指定CHARACTER SET,也不指定COLLATE,則使用數據庫默認。
CREATE TABLEmytable
(
colum1INT,
colum2VARCHAR(10)
)DEFAULT CHARACTER SEThebrew
COLLATE hebrew_general_ci;
除了能指定字符集和校對的表范圍外,MySQL還允許對每個列設置它們,如下所示:
CREATE TABLEmytable
(
colum1INT,
colum2 VARCAHR(10),
colum3 VARCAHR(10) CHARACTER SETlatin1 COLLATE latin1_general_ci
)DEFAULT CHARACTER SEThebrew
COLLATE hebrew_general_ci;-------這里對整個表以及一個特定的列指定了CHARACTER SET和COLLATE
如前所述,校對在對用ORDER BY子句檢索出來的數據排序時起很重要的作用。如果你需要用與創建表時不同的校對順序排序特定的SELECT語句,可以在SELECT語句自身中進行:
SELECT * FROMcustomersORDER BYlastname, fistname COLLATE latin1_general_cs;----此SELECT使用COLLATE指定一個備用的校對順序(在這個例子中,為區分大小寫的校對)。這顯然會影響到結果排序的次序。
ps:臨時區分大小寫:上面的SELECT語句演示了在通常不區分大小寫的表上進行區分大小寫搜索的一種技術。當然,反過來也是可以的。
SELECT的其他COLLATE子句:除了這里可以看到的在ORDER BY子句中使用以外,COLLATE還可以用于GROUP BY、HAVING、聚集函數、別名等。
**值得注意的是,如果絕對需要,串可以在字符集之間進行轉換。為此,使用Cast()或Convert()函數。
----安全管理
--訪問控制
MySQL服務器的安全基礎是:用戶應該對他們需要的數據具有適當的訪問權,既不能多也不能少。換句話說,用戶不能對過多的數據具有過多的訪問權。
考慮以下內容:
1、多數用戶只需要對表進行讀和寫,但少數用戶甚至需要能創建和刪除表
2、某些用戶需要讀表,但可能不需要更新表
3、你可能想允許添加數據,但不允許他們刪除數據
4、某些用戶(管理員)可能需要處理用戶賬號的權限,但多數用戶不需要
5、你可能想讓用戶通過存儲過程訪問數據,但不允許他們直接訪問數據
6、你可能想根據用戶登錄的地點限制對某些功能的訪問
這些都只是例子,但有助于說明一個重要的事實,即你需要給用戶提供他們所需的訪問權,且僅提供他們所需的訪問權。這就是所謂的訪問控制,管理訪問控制需要創建和管理用戶賬號。
ps:使用MySQL Administrator:MySQL Administrator提供了一個圖形用戶界面,可用來管理用戶及賬戶權限。MySQL Administrator在內部利用本章介紹的語句,使用能交互地、方便地管理訪問控制。
我們知道,為了執行數據庫操作,需要登錄MySQL。MySQL創建一個名為root的用戶賬戶,它對整個MySQL服務器具有完全的控制。但在實際應用中,應該創建一系列的賬號,有的用于管理,有的供用戶使用,有的供開發人員使用。
ps:防止無意的錯誤:重要的是注意到,訪問控制的目的不僅僅是防止用戶的惡意企圖。數據夢魘更為常見的是無意識錯誤的結果,如打錯MySQL語句,在不適合的數據庫中操作或其他一些用戶錯誤。通過保證用戶不能執行他們不應該執行的語句,訪問控制有助于避免這些情況的發生。
不要使用root:應該嚴肅對待root登錄的使用。僅在絕對需要時使用它(或許在你不能登錄其他管理賬號時使用)。不應該在日常的MySQL操作中使用root。
--管理用戶
MySQL用戶賬號和信息存儲在名為mysql數據表中。一般不需要直接訪問mysql數據庫和表,但有時需要直接訪問。需要直接訪問它的時機之一是在需要獲得所有用戶賬號列表時。為此,可使用以下代碼:
USEmysql;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要求你至少給出以下信息:
1、要授予的權限
2、被授予訪問權限的數據庫或表
3、用戶名
以下給出GRANT的用法:
GRANT SELECT ON crashcourse.* TO bforta;
SHOW GRANT反應這個更改:
SHOW GRANT FOE beforta;
GRANT的反操作為REVOKE,用它來撤銷特定的權限,舉個例子:
REVOKE SELECT ON crashcourse.* FROM bforta;
GRANT和REVOKE可在幾個層次上控制訪問權限:
1、整個服務器,使用GRANT ALL和REVOKE ALL
2、整個數據庫,使用ON database.*
3、特定的表,使用ON database.table
4、特定的列
5、特定的存儲過程
以下列出可以授予或撤銷的每個權限:
權限
權限
說明
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更新當前登錄用戶的口令。
----數據庫維護
--備份數據
解決普通的文件副本不一定總是有效的方案:
1、使用命令行使用程序mysqldump轉儲所有數據庫內容到某個外部文件。在進行常規備份前這個實用程序應該正常運行,以便能正確地備份轉儲文件
2、可用命令行實用程序mysqlhotcopy從一個數據庫復制所有數據(并非所有數據庫引擎都支持這個實用程序)
3、可以使用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命令行選項:
1、--help顯示幫助———一個選項列表
2、--safe-mode裝載減去某些最佳配置的服務器
3、--verbose顯示全文本消息(為獲得更詳細的幫助消息與--help聯合使用)
4、--version顯示版本信息然后退出
--查看日志文件
MySQL維護管理員依賴的一系列日志文件。主要的日志文件有以下幾種:
1、錯誤日志。它包含啟動和關閉問題以及任意關鍵錯誤的細節。此日志通常名為hostname.err,位于data目錄中。此日志名可用--log-error命令行選項更改。
2、查詢日志。它記錄所有MySQL活動,在診斷問題時非常有用。此日志文件可能會很快地變得非常大,因此不應該長期使用它。此日志文件通常名為hostname.log,位于data目錄中。此名字可以用--log命令行選項更改。
3、二進制日志。它記錄更新過數據(或者可能更新過的數據)的所有語句。此日志通常名為hostname-bin,位于data目錄內。此名字可以用--log-bin命令行選項更改。注意,這個日志文件是MySQL5中添加的,以前的MySQL版本中使用的是更新日志。
4、緩慢查詢日志。此日志記錄執行緩慢的任何查詢。這個日志在確定數據庫何處需要優化很有用。此日志通常名為hostname-slow.log,位于data目錄中。此名字可以用--log-slo-queries命令行選項更改。
在使用日志時,可用FLUSH LOGS語句來刷新和重新開始所有日志文件。
----改善性能
1、首先,MySQL(與所有DBMS一樣)具有特定的硬件建議。在學習和研究MySQL時,使用任何舊的計算機作為服務器都可以。但對用于生產的服務器來說,應該堅持遵循這些硬件建議
2、一般來說,關鍵的生產DBMS應該運行在自己的專用服務器上
3、MySQL是用一系列的默認設置預先設置的,這些設置開始通常是很好的。但過一段時間后你可能需要調整內存分配、緩沖區大小等。(為查看當前設置,可使用SHOW VARIABLES;和SHOW STATUS;)
4、MySQL是一個多用戶多線程的DBMS,換言之,它經常同時執行多個任務。如果這些任務中的某一個執行緩慢,則所有請求都會執行緩慢。如果你遇到顯著的性能不良,可使用SHOW PROCESSLIST顯示所有活動進程(以及它們的線程ID和執行時間)。你還可以用KILL命令終結某個特定的進程(使用這個命令需要作為管理員登錄)
5、總是有不止一種方法編寫同一條SELECT語句。應該試驗聯結、并、子查詢等,找出最佳方法
6、使用EXPLAIN語句讓MySQL解釋它將如何執行一條SELECT語句
7、一般來說,存儲過程執行的比一條一條地執行其中的各條MySQL語句快
8、應該總是使用正確的數據類型
9、決不要檢索比需要還要多的數據。換言之,不要用SELECT *(除非你真正需要每個列)
10、有的操作(包括INSERT)支持一個可選的DELAYED關鍵字,如果使用它,將把控制立即返回給調用程序,并且一旦有可能就實際執行該操作
11、在導入數據時,應該關閉自動提交。你可能還想刪除索引(包括FULLTEXT索引),然后在導入完成后再重建它們
12、必須索引數據庫表以改善數據檢索的性能。確定索引什么不是一件微不足道的任務,需要分析使用的SELECT語句以找出重復的WHERE和ORDER BY子句。如果一個簡單的WHERE子句返回結果所花的時間太長,則可以斷定其中使用的列(或幾個列)就是需要索引的對象
13、你的SELECT語句中有一系列復雜的OR條件嗎?通過使用多條SELECT語句和連接它們的UNION語句,你能看到極大的性能的改進
14、索引改善數據索引的性能,但損害數據插入、刪除和更行的性能。如果你有一些表,它們收集數據且不經常被搜索,則在有必要之前不要索引它們。(索引可根據需要添加和刪除)
15、LIKE很慢。一般來說,最好使用FULLTEXT而不是LIKE
16、數據庫是不斷變化的實體。一組優化良好的表一會兒后可能就面目全非了。由于表的使用和內容的更改,理想的優化和配置也會改變
17?、最重要的規則就是,每條規則在某些條件下都會被打破
ps:瀏覽文檔:http://dev.mysql.com/doc,更多的內容參考MySQL手冊
------------------------------------------------
本文章參考自《mysql必知必會》
《新程序員》:云原生和全面數字化實踐50位技術專家共同創作,文字、視頻、音頻交互閱讀總結
以上是生活随笔為你收集整理的mysql中以下正确的sql是_总结MySQL中SQL语法的使用的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: as无效 mysql_mysql 排它锁
- 下一篇: mysql replication 协议