學(xué)習(xí)mysql的幾天,將筆記整理一下
SQL(Structured Query Language): 結(jié)構(gòu)化查詢語言。
數(shù)據(jù)庫軟件稱為: DBMS(數(shù)據(jù)管理系統(tǒng)庫)
DBMS可分為兩類:
- 基于共享文件系統(tǒng)的DBMS。Microsoft Access、FileMaker
- 基于客戶機(jī)——服務(wù)器的DBMS。MySQL、Oracle、Microsoft SQL Server
數(shù)據(jù)庫(database): 數(shù)據(jù)庫是一個(gè)以某種有組織的方式存儲(chǔ)的數(shù)據(jù)集合。通常是一個(gè)文件或一組文件。
表(table): 是一種結(jié)構(gòu)化的文件,可用來存儲(chǔ)某種特定類型的數(shù)據(jù)。數(shù)據(jù)庫中的每個(gè)表都有一個(gè)名字,用來標(biāo)識(shí)自己,此名字是唯一的。
列(column): 表中的一個(gè)字段,所有表都是由一個(gè)或多個(gè)列組成的。
分解數(shù)據(jù): 正確的將數(shù)據(jù)分解成多個(gè)列極為重要,通過把他們分解開,才有可能利用特定的列對(duì)數(shù)據(jù)進(jìn)行排序和過濾。
數(shù)據(jù)類型(datatype): 數(shù)據(jù)類型限制可存儲(chǔ)在列中的數(shù)據(jù)類型。
行(row):表中的一條記錄。
主鍵(primary key):
外鍵(foreign key):
自增量(auto_increment):
默認(rèn)值(default):
描述(comment):
存儲(chǔ)引擎
- engine=InnoDB:可靠的事務(wù)處理引擎,不支持全文搜索。
- MyISAM:是一個(gè)性能極高的引擎,支持全文搜索,但不支持事務(wù)處理。
- MEMORY:功能等同于MyISAM,但由于數(shù)據(jù)存儲(chǔ)在內(nèi)存(不是磁盤中),速度很快,特別適合于臨時(shí)表。
注意:外鍵不能跨引擎。
MySQL是一種DBMS,即一種數(shù)據(jù)庫管理軟件。
MySQL的特點(diǎn):
- 可伸縮性(scale):
====================================================
show database;
show tables;
show colunms from table_name;
show status; 用于顯示廣泛是服務(wù)器狀態(tài)信息
show create database / show create table; 顯示創(chuàng)建特定數(shù)據(jù)庫或表的SQL語句
show grants; 從來顯示授權(quán)用戶(所有用戶或特定用戶)的安全權(quán)限
show errors / show warnings; 顯示服務(wù)器錯(cuò)誤或警告的信息
help show 來獲取更多的命令
檢索數(shù)據(jù)
select [distinct] column_name, .... from table_name;
distinct: 只返回不同的值(該關(guān)鍵字應(yīng)用于所有列)
使用通配符:
select * from table_name;
檢索返回指定的條數(shù):
limit num;
從指定位置開始檢索指定的條數(shù):
limit start_index, num; (index起始值為0)
limit num offset start_index;
注意:有的時(shí)候需要使用完全限定名:
db_name.table_name
table_name.column_name
排序:
按單個(gè)列排序:
order by column_name [DESC|ASC];
按多個(gè)列排序:(每個(gè)列都要指明排序的方向)
order by column_name1 [DESC|ASC], column_name2 [DESC|ASC], ...;
在按多個(gè)列排序時(shí),排序完全按所規(guī)定的順序進(jìn)行。(僅有在多個(gè)行具有相同的column_name1時(shí),才會(huì)按column_name2排序。如果column_name1中的所有值都是唯一的,則不會(huì)按column_name2排序)
默認(rèn)的排序方向?yàn)樯颍ˋSC):
ASC ===> A-->Z
DESC===> Z-->A
SELECT子句的順序:
- select
- from
- where
- group by
- having
- order by
- limit
過濾數(shù)據(jù)
使用 WHERE 子句
MySQL在執(zhí)行匹配時(shí),默認(rèn)不區(qū)分大小寫。
使用單引號(hào)''限定字符串,
where子句的操作符:
= 等于
<> 不等于
!= 不等于
< 小于
<= 小于等于
> 大于
>= 大于等于
BETWEEN 在指定的兩個(gè)值之間
BETWEEN start_value AND end_value; (包括 start_value和end_value)
空值檢查:
WHERE column_name IS NULL;
組合 WHERE 子句:
AND操作符,可以添加多個(gè)過濾條件,使用 AND 連接。OR操作符
注意:(操作時(shí)使用圓括號(hào)明確地分組操作符。)IN (value1, value2)指定條件的范圍
注意:IN 操作符 與 OR 操作符功能相同,可以包含其他的 SELECT 語句,能夠更動(dòng)態(tài)地建立WHERE子句。NOT操作符
用來否定后跟的條件。
注意:MYSQL中支持使用 MOT 對(duì)IN、BETWEEN、EXISTS子句取反的操作
用通配符進(jìn)行過濾:
LIKE 子句, 后跟匹配的條件
百分號(hào)(%)通配符:表示任意字符出現(xiàn)任意次數(shù)。
'jre%'---- 以 jre 開頭
'%jar%'--- 包含 jar下劃線(_)通配符:只匹配單個(gè)字符。
注意: 通配符的搜索一般要比其他搜索所花的時(shí)間更長(zhǎng)。
- 不要過度使用通配符,如果其他的操作符能達(dá)到相同的目的,應(yīng)該使用其他的操作符。
- 除非絕對(duì)有必要,否則不要把他們用在搜索模式的開始處,搜索起來是最慢的。
- 注意使用通配符所在位置。
WHERE子句內(nèi)使用正則表達(dá)式進(jìn)行搜索:
REGEXP子句,后跟匹配的條件。默認(rèn)匹配不區(qū)分大小寫,
可使用REGEXP BINARY 子句來是的區(qū)分大小寫。
'.' :表示匹配任意一個(gè)字符。'.name'
'|': 正則表達(dá)式中的OR操作符。'a|b'-----匹配a或b
'[]':匹配任何單一字符,也是OR操作符飛另一種形式。[abc]---匹配a或b或c
'[^abc]'----匹配除a、b、c以外的字符。
'[0-9]':匹配0~9.
'[a-z]'
'\\.':表示查找 '.'
計(jì)算字段
拼接字段:
在MySQL中 Concat() 函數(shù)用來拼接字段串,即拼接在一起顯示特定的信息。
多個(gè)字段用,隔開。
RTirm()函數(shù),刪除數(shù)據(jù)右側(cè)多余的空格。
LTirm()函數(shù),刪除數(shù)據(jù)左側(cè)多余的空格。
使用別名:
AS alias_name;
SELECT Concat(RTrim(vend_nmae), '(', RTrim(vend_country), ')') AS wend_title FROM vendors ORDER BY vend_name;
列別名:
表別名:表別名只在查詢中使用,表別名不返回到客戶機(jī)。
執(zhí)行算術(shù)計(jì)算:
+
-
*
/
SELECT prod_id, quantity, item_price,
quantity*item_price AS expanded_price
FROM orderitems
WHERE order_num = 20005;
數(shù)據(jù)分組
group by
SELECT vend_id, COUNT(*) AS num_prods
FROM products
GROUP BY vend_id;
過濾分組:
having
having 支持所有 where操作。
SELECT cust_id, COUNT(*) AS orders
FROM orders
GROUP BY cust_id
HAVING COUNT(*) >= 2;
having 和 where 的區(qū)別:
- where 過濾行,having過濾分組;
- where 在數(shù)據(jù)分組前進(jìn)行過濾,having在數(shù)據(jù)分組后進(jìn)行過濾;
- where排除的行不包括在分組中。
子查詢
子查詢:嵌套在其他查詢語句中的查詢
聯(lián)結(jié)
foreign key
外鍵:為某個(gè)表中的一列,它包含另一個(gè)表的主鍵值,定義了兩個(gè)表之間的關(guān)系。
聯(lián)結(jié):
是一種機(jī)制,用來在一條 SELECT 語句中關(guān)聯(lián)表。
使用特殊語法,可以聯(lián)結(jié)多個(gè)表返回一組輸出。聯(lián)結(jié)在運(yùn)行時(shí)關(guān)聯(lián)表中正確的行。
聯(lián)結(jié)在實(shí)際的數(shù)據(jù)庫表中并不存在,聯(lián)結(jié)由MySQL根據(jù)需要建立,它存在于查詢的執(zhí)行當(dāng)中。
SELECT vend_name, prod_name, prod_price
FROM vendors, products
WHERE vendors.vend_id = products.vend_id
ORDER BY vend_name, prod_name;
注意:
- 在聯(lián)結(jié)中的WHERE子句是很關(guān)鍵的,應(yīng)該保證所有聯(lián)結(jié)都有WHERE子句,否則MySQL將返回比想要的數(shù)據(jù)多的多的數(shù)據(jù)。
- 還應(yīng)保證WHERE子句的正確性,不正確的過濾條件將導(dǎo)致mysql返回不正確的數(shù)據(jù)。
內(nèi)部聯(lián)結(jié)(最常用的形式):
到目前為止,所有的聯(lián)結(jié)都稱為等值聯(lián)結(jié),它基于兩個(gè)表之間的相等測(cè)試,這種聯(lián)結(jié)也稱為內(nèi)部聯(lián)結(jié)。
SELECT vend_name, prod_name, prod_price
FROM vendors INNER JOIN products
ON vendors.vend_id = products.vend_id;
這樣的寫法與上邊的寫法的結(jié)果是等同的,
聯(lián)結(jié)多個(gè)表:
SQL對(duì)于一條SELECT語句中可以聯(lián)結(jié)的表的數(shù)目沒有限制。
創(chuàng)建的規(guī)則也基本相同,首先列出所有表,然后定義表之間的關(guān)系。
SELECT prod_name, vend_name, prod_price, quantity
FROM orderitems, vendors, products
WHERE products.vend_id = vendors.vend_id
AND orderitems.prod_id = products.prod_id
AND order_num = 20005;
自聯(lián)結(jié):
用一個(gè)問題來說明
SELECT prod_id, prod_name
FROM products
WHERE vend_id = (SELECT vend_id FROM products WHERE prod_id = 'DTNTR');
下面使用自聯(lián)結(jié)將達(dá)到相同的效果:
SELEC 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';
自聯(lián)結(jié)通常作為外部語句用來代替從相同表中檢索數(shù)據(jù)時(shí)使用的子查詢語句。
自然聯(lián)結(jié):
外部聯(lián)結(jié):
許多聯(lián)結(jié)將一個(gè)表中的行與另一個(gè)表中的行相關(guān)聯(lián)。但有時(shí)候會(huì)需要包含沒有關(guān)聯(lián)行的那些行。這種類型的聯(lián)結(jié)稱為外部聯(lián)結(jié)。
LEFT|RIGHT OUTER JOIN 表示從左邊表或右邊表中選擇所有行。
組合查詢
多數(shù)SQL查詢都只包含從一個(gè)或多個(gè)表中返回?cái)?shù)據(jù)的單條SELECT語句。
MySQL也允許執(zhí)行多個(gè)查詢(多條SELECT語句),并將結(jié)果作為單個(gè)查詢結(jié)果集返回。
有兩種情況需要使用組合查詢:
- 在單個(gè)查詢中從不同的表返回類似結(jié)構(gòu)的數(shù)據(jù)。
- 對(duì)單個(gè)表執(zhí)行多個(gè)查詢,按單個(gè)查詢返回?cái)?shù)據(jù)。
UNION
- 必須由兩條或兩條以上的SELECT語句組成,SELECT語句之間用UNION關(guān)鍵字分割。
- UNION中的每個(gè)查詢必須包含相同的列,表達(dá)式或聚集函數(shù)(各個(gè)列不需要以相同的次序列出)。
- 列數(shù)據(jù)類型必須兼容,類型不必完全相同,但必須是DBMS可以隱含轉(zhuǎn)換的類型(例如不用的數(shù)值類型或不同的日期類型)。
消掉重復(fù)的行:
UNION 默認(rèn)返回結(jié)果會(huì)消掉重復(fù)的行;
UNION ALL 則不消掉重復(fù)的行。
對(duì)組合查詢結(jié)果進(jìn)行排序:
SELECT語句的輸出用order by 語句排序,再用 UNION 組合查詢時(shí),只能使用一條 order by子句,
它必須出現(xiàn)在最后一條SELECT語句之后。
可以組合不同的表
插入數(shù)據(jù)
再插入數(shù)據(jù)時(shí)需要注意的問題:
- 一般使用明確給出列的列表的insert語句。即使表結(jié)構(gòu)發(fā)生改變,也可以正確插入。
- 省略某些列:
省略列必須滿足以下的條件:
該列定義為允許NULL值(無值或空值)。
在表的定義中給出默認(rèn)值。
不滿足上述的條件則會(huì)產(chǎn)生一條錯(cuò)誤的消息,并且相應(yīng)的行插入不成功。
使用 insert low_priority into 語句可以指示mysql降低insert語句的優(yōu)先級(jí)。
因?yàn)閕nsert語句執(zhí)行很耗時(shí),這樣可以提高性能。
這也適用于update和delete語句。插入檢索出的數(shù)據(jù)
insert into table_name(column_name1, column_name2,...)
values(value1, value2...)
select column_nam1, column_name2,... from table_name;
更新語句
update table_name set colunm_name1=value1, column_name2=value2,... where 過濾條件;
如果用 update 更新語句更新多行,并且在更新這些行找中的一行或者多行出現(xiàn)錯(cuò)誤,則整個(gè)的update操作將被取消。
為了即使是發(fā)生了錯(cuò)誤,也繼續(xù)進(jìn)行更新,可使用 ignore 關(guān)鍵字。
update ignore table_name set....;
刪除語句
delete from table_name where 過濾條件;
- delete語句刪除表中的行,甚至是所有的行,但是不刪除表本身。
- 若想要更快的刪除表中的所有數(shù)據(jù),可使用:
truncate table 語句,(實(shí)際是刪除了原來的表并重新創(chuàng)建了一個(gè)表,而不是逐行刪除表中的數(shù)據(jù))。
對(duì)于表的操作
創(chuàng)建表:
create table [IF NOT EXISTS] table_name();
更新表:
alert table table_name 要操作的語句;
添加一個(gè)字段
ALERT TABLE vendors ADD vend_phone char(20);
刪除一個(gè)字段
ALERT TABLE vendors DROP COLUMN vend_phone;
alert的一種常見操作是定義外鍵。
ALERT TABLE table_name ADD CONSTRAINT fk_tableName1_tableName2 FOREIGN KEY (column_name) REFERENCES table_name(column_name);
刪除表:
drop table table_name;
重命名表:
rename table old_table_name to new_table_name;
全文搜索
MyISAM引擎支持全文搜索。
在使用全文本搜索時(shí),MySQL不需要分別查看每個(gè)行,不需要分別分析和處理每個(gè)詞,MySQL創(chuàng)建指定列中個(gè)詞的一個(gè)索引,搜索可以針對(duì)這些詞進(jìn)行。這樣,MySQL就可以快速有效地決定哪些詞匹配(哪些行包含他們),哪些詞不匹配 ,他們的匹配頻率,等等。
使用全文本搜索:
為了進(jìn)行全文本搜索,必須索引被搜索的列,而且要隨著數(shù)據(jù)的改變不斷地重新索引,在對(duì)表列進(jìn)行適當(dāng)?shù)脑O(shè)計(jì)后,MySQL會(huì)自動(dòng)進(jìn)行所有的索引和重新索引。
啟用全文搜索支持(創(chuàng)建索引):
一般在創(chuàng)建表時(shí)啟用全文本搜索,
CREATE TABLE productnotes(
note_id INT NOT NULL AUTO_INCREMENT,
prod_id VARCHAR(10) NOT NULL,
note_date DATETIME NOT NULL,
note_text TEXT NULL,
PRIMARY KEY (note_id),
FULLTEXT (note_text) // 多個(gè)索引列用逗號(hào)隔開
) ENGINE = MyISAM;
在定義之后,MySQL會(huì)自動(dòng)的維護(hù)該索引,在增加、更新、修改行時(shí),索引隨之自動(dòng)更新。
進(jìn)行全文搜索:
在索引之后,使用兩個(gè)函數(shù) Match() 和 Against() 執(zhí)行全文搜索。
Match()--指定被搜索的列
Against()--指定要使用的搜索表達(dá)式(要搜索的東西)
SELECT note_text FROM productnotes
WHERE Match(note_text) Against('rabbit');
注意:傳遞給Match()的值必須與 FULL TEXT() 定義中的相同,如果指定多個(gè)列,則必須列出他們(而且次序正確)。
搜索不區(qū)分大小寫,除非使用BINARY方式。
全文本搜搜的一個(gè)重要的部分就是會(huì)對(duì)搜索結(jié)果進(jìn)行排,具有較高等級(jí)的先返回。
(兩個(gè)行包含同樣的詞,但包含該詞作為第3個(gè)詞的行的等級(jí)比作為第20個(gè)詞的行高)
使用查詢擴(kuò)展:
查詢擴(kuò)展用來設(shè)法放寬所返回的全文本搜索結(jié)果的范圍。(返回相關(guān)的數(shù)據(jù),也就是數(shù)有聯(lián)系的)
SELECT note_text FROM productnotes
WHERE Match(note_text) Against('rabbit' WITH QUERY EXPANSION );
布爾文本搜索:
布爾文本搜索是MySQL支持全文本搜索的另外一種形式。
布爾文本搜索可以提供關(guān)于如下內(nèi)容的細(xì)節(jié):
- 要匹配的詞
- 要排斥的詞(某行包含該詞將不返回)
- 排列提示(指定某些詞比其他詞更重要,重要的詞等級(jí)更高)
- 表達(dá)式分組
- 另外的一些內(nèi)容
SELECT note_text FROM productnotes
WHERE Match(note_text) Against('rabbit' IN BOOLEAN MODE );
匹配包含 heavy 但不包含任意以 rope 開頭的詞的行,如下:
SELECT note_text FROM productnotes
WHERE Match(note_text) Against('heavy -rope*' IN BOOLEAN MODE );
全文本布爾搜索操作符:
+ :包含,詞必須存在
-:排除,詞必須不出現(xiàn)
> :包含,且增加等級(jí)值
<:包含,且減小等級(jí)值
() :用于組成子表達(dá)式
~ :取消一個(gè)詞的排序值
*:
"":定義一個(gè)短語
視圖
MySQL5 增加了對(duì)視圖的支持。
視圖(View):是虛擬的表,與包含數(shù)據(jù)的表不一樣,視圖只包含使用時(shí)動(dòng)態(tài)檢索數(shù)據(jù)的查詢。
視圖的一些常見應(yīng)用:
- 重用SQL語句。
- 簡(jiǎn)化復(fù)雜的SQL操作。在編寫查詢后,可以方便的重用他而不必知道它的基本查詢細(xì)節(jié)。
- 使用表的組成部分而不是整個(gè)表。
- 保護(hù)數(shù)據(jù)。可以給用戶授予表的特定部分的訪問權(quán)限而不是整個(gè)表的訪問權(quán)限。
- 更改數(shù)據(jù)格式和表示。視圖可返回與底層表的表示和格式不同的數(shù)據(jù)。
在視圖創(chuàng)建之后,可以用域表基本相同的操作方式來來操作它。
可以對(duì)視圖執(zhí)行select操作,過濾、排序、聯(lián)結(jié)到其他視圖或表、添加數(shù)據(jù)、更新數(shù)據(jù)(添加和更新數(shù)據(jù)存在某些限制)。
視圖的規(guī)則和限制:
- 視圖必須唯一命名。
- 對(duì)于可以創(chuàng)建的視圖數(shù)目沒有限制。
- 為了創(chuàng)建視圖,必須具有足夠的訪問權(quán)限。通常由數(shù)據(jù)庫管理人員授予。
- 視圖可以嵌套。即可以使用視圖中的檢索查詢來構(gòu)造一個(gè)視圖。
- order by 可以用在視圖中,但如果從該視圖中檢索數(shù)據(jù)的select中也含有order by,
那么該視圖中的order by 將被覆蓋。 - 視圖不能索引,也不能有關(guān)聯(lián)的觸發(fā)器和默認(rèn)值。
- 視圖可以和表一起使用。比如和表聯(lián)結(jié)。
創(chuàng)建視圖:
create view as select語句
查看創(chuàng)建的視圖:
show create view view_name;
刪除視圖:
drop view view_name;
更新視圖:
- 先使用
drop,在用create - 直接使用
create or replace view
如果要更新的視圖不存在,該語句會(huì)創(chuàng)建一個(gè)視圖;
如果要更新的視圖存在,該語句會(huì)替換原有的視圖。
視圖是可更新的(insert、update、delete),更新一個(gè)是將更新其基表。
并非所有的視圖都是可更新的,如果視圖定義中有如下的操作,則不能進(jìn)行視圖的更新:
- 分組(使用group by或 having)
- 聯(lián)結(jié)
- 子查詢
- 并
- 聚集函數(shù)
- distinct
- 導(dǎo)出(計(jì)算)列
注意:一般應(yīng)該將視圖用于檢索,而不是更新。
存儲(chǔ)過程
MySQL5增加了對(duì)存儲(chǔ)過程的支持。
存儲(chǔ)過程:為以后的使用而保存的一條或多條MySQL語句的集合。
為什么要使用存儲(chǔ)過程:
- 通過把處理封裝在容易使用的單元中,簡(jiǎn)化復(fù)雜的操作。
- 不再反復(fù)建立一系列的處理步驟,保證了數(shù)據(jù)的完整性。
比如,開發(fā)人員和應(yīng)用程序都使用同一存儲(chǔ)過程,則所使用的代碼都是相同的。這樣就保證數(shù)據(jù)的一致性,不容易出錯(cuò)。 - 簡(jiǎn)化對(duì)變動(dòng)的管理。如表名、列名、或業(yè)務(wù)邏輯等有變化,只需改動(dòng)存儲(chǔ)過程的代碼。
- 提高性能。
- 存儲(chǔ)過程可以用來編寫功能更強(qiáng)更靈活的代碼。
創(chuàng)建存儲(chǔ)過程需要訪問權(quán)限,這通常是由數(shù)據(jù)庫管理員賦予。
創(chuàng)建存儲(chǔ)過程:
create procedure procedure_name([參數(shù)1, 參數(shù)2, ...])
begin
存儲(chǔ)過程執(zhí)行代碼(過程體)
end;
使用存儲(chǔ)過程:
call procedure_name([@參數(shù)1, @參數(shù)2, ...]);
刪除存儲(chǔ)過程:
drop procedure procedure_name;
僅當(dāng)存在時(shí)刪除,不存在會(huì)產(chǎn)生錯(cuò)誤,可使用:
drop procedure if exists procedure_name;
參數(shù):
一般存儲(chǔ)過程并不返回結(jié)果,而是把結(jié)果返回給你指定的變量。
CREATE PROCEDURE productpricing(
OUT p1 DECIMAL(8, 2),
OUT p2 DECIMAL(8, 2),
OUT p2 DECIMAL(8, 2)
)
BEGIN
SELECT min(prod_price)
INTO p1
FROM products;
SELECT max(prod_price)
INTO p2
FROM products;
SELECT avg(prod_price)
INTO p3
FROM products;
END;
該存儲(chǔ)過程接受了三個(gè)參數(shù),每個(gè)參數(shù)必須具有指定的類型
IN傳遞給存儲(chǔ)過程
OUT 從存儲(chǔ)工程傳出
INOUT對(duì)存儲(chǔ)過程傳入和傳出
INTO 保存到相應(yīng)的變量
注意:不能通過一個(gè)參數(shù)返回多個(gè)行和列。
使用該存儲(chǔ)過程:
CALL productpricing(@pricelow, @pricehigh, @priceaverage);
顯示該存儲(chǔ)過程的結(jié)果:
SELECT @pricelow, @pricehigh, @priceaverage;
CREATE PROCEDURE ordertotal(
IN onumber INT,
OUT ototal DECIMAL(8,2)
)
BEGIN
SELECT sum(item_price*quantity)
FROM orderitems
WHERE order_num = onumber
INTO ototal;
END;
CALL ordertotal(20005, @total);
SELECT @total;
局部變量:
在過程體中定義局部變量(BEGIN--END之間),使用:
DECLARE taxrate INT DEFAULT 6;
局部變量要指定變量名和數(shù)據(jù)類型。
CREATE PROCEDURE ordertotal(
IN onumber INT,
IN taxable BOOLEAN,
OUT ototal DECIMAL(8,2)
)
BEGIN
-- 創(chuàng)建局部變量
DECLARE total DECIMAL(8, 2);
DECLARE taxrate INT DEFAULT 6;
SELECT sum(item_price*quantity)
FROM orderitems
WHERE order_num = onumber
INTO total;
-- ELSEIF | ELSE
IF taxable THEN
SELECT total+(total/100*taxrate) INTO total;
END IF;
SELECT total INTO ototal;
END;
-- 0為假,非0為真
CALL ordertotal(20005, 1, @total);
SELECT @total;
檢查存儲(chǔ)過程:
顯示創(chuàng)建存儲(chǔ)過程的create語句:
show create procedure procedure_name;
獲得詳細(xì)的存儲(chǔ)信息列表:
show procedure status;
游標(biāo)
MySQL5添加了對(duì)游標(biāo)的支持。
MySQL檢索操作返回一組稱為結(jié)果集的行。返回的行都是與sql語句相匹配的行(零行或多行)。有的時(shí)候是需要在檢索出來的行中前進(jìn)或后退一行或多行,使用簡(jiǎn)單的select語句是沒有辦法得到的。這就是使用游標(biāo)的原因了。
游標(biāo)(cursor):是一個(gè)存儲(chǔ)在mysql服務(wù)器上的數(shù)據(jù)庫查詢,它不是一條select語句。而是被該語句檢索出來的結(jié)果集。
在存儲(chǔ)了游標(biāo)之后,應(yīng)用程序可以根據(jù)需要滾動(dòng)或?yàn)g覽其中的數(shù)據(jù)。
游標(biāo)主要用于交互式應(yīng)用,其中用戶需要滾動(dòng)屏幕上的數(shù)據(jù),并對(duì)數(shù)據(jù)進(jìn)行瀏覽或作出更改。
MySQL游標(biāo)只能用于存儲(chǔ)工程(和函數(shù))。
使用游標(biāo)的步驟:
- 在使用游標(biāo)前必須聲明(定義)它,這個(gè)過程實(shí)際上沒有檢索數(shù)據(jù),它只是定義要使用的select語句。
- 一旦聲明后,必須打開游標(biāo)以供使用。這個(gè)過程要用到前面定義的select語句把數(shù)據(jù)實(shí)際檢索出來。
- 對(duì)于填有數(shù)據(jù)的游標(biāo),根據(jù)需要取出(檢索)各行。
- 在結(jié)束游標(biāo)使用時(shí),必須關(guān)閉游標(biāo)。
在聲明游標(biāo)后可根據(jù)需要頻繁地打開和關(guān)閉游標(biāo)。在游標(biāo)打開后,可根據(jù)需要頻繁地執(zhí)行取操作。
創(chuàng)建游標(biāo):
游標(biāo)使用 DECLARE,DECLARE命名游標(biāo),并定義相應(yīng)的select 語句。
CREATE PROCEDURE processorders()
BEGIN
DECLARE ordernumbers CURSOR FOR
SELECT order_name FROM orders;
END;
存儲(chǔ)過程處理完后,游標(biāo)就消失(因?yàn)樗窒抻诖鎯?chǔ)過程)。
打開和關(guān)閉游標(biāo):
在定義了游標(biāo)之后就可以打開它。
OPEN ordernumbers;
在處理open語句時(shí)執(zhí)行查詢,存儲(chǔ)檢索出來的數(shù)據(jù)以供瀏覽和滾動(dòng)。
關(guān)閉:
CLOSE ordernumbers;
close釋放游標(biāo)使用的所有內(nèi)部?jī)?nèi)存和資源,每個(gè)游標(biāo)在不需要時(shí)都應(yīng)該關(guān)閉。
游標(biāo)關(guān)閉后,沒有重新打開是不能使用的。
使用過的游標(biāo)不需要再次聲明,使用open打開就可以了。
如果沒有明確的關(guān)閉游標(biāo)(CLOSE),mysql會(huì)在 END 時(shí)自動(dòng)關(guān)閉它。
CREATE PROCEDURE processorders()
BEGIN
DECLARE ordernumbers CURSOR FOR
SELECT order_name FROM orders;
OPEN ordernumbers;
相應(yīng)的處理操作
CLOSE ordernumbers;
END;
使用游標(biāo)數(shù)據(jù):
使用 FETCH 可以訪問它的每一行:
CREATE PROCEDURE processorders()
BEGIN
DECLARE o INT;
DECLARE ordernumbers CURSOR FOR
SELECT order_name FROM orders;
OPEN ordernumbers;
FETCH ordernumbers INTO o;
CLOSE ordernumbers;
END;
該例只訪問的是第一行數(shù)據(jù)。
CREATE PROCEDURE processorders()
BEGIN
DECLARE done BOOLEAN DEFAULT 0;
DECLARE o INT;
DECLARE ordernumbers CURSOR FOR
SELECT order_name FROM orders;
-- SQLSTATE '02000' 是一個(gè)未找到條件
DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET done=1;
OPEN ordernumbers;
REPEAT
FETCH ordernumbers INTO o;
UNTIL done END REPEAT;
CLOSE ordernumbers;
END;
循環(huán)檢索數(shù)據(jù),從第一行到最后一行。
CREATE PROCEDURE processorders()
BEGIN
DECLARE done BOOLEAN DEFAULT 0;
DECLARE o INT;
DECLARE t DECIMAL(8, 2);
DECLARE ordernumbers CURSOR FOR
SELECT order_name FROM orders;
DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET done=1;
DROP TABLE IF EXISTS ordertotals;
CREATE TABLE IF NOT EXISTS ordertotals(
order_num INT,
total DECIMAL(8, 2)
);
OPEN ordernumbers;
REPEAT
FETCH ordernumbers INTO o;
CALL ordertotal(o, 1, t);
INSERT INTO ordertotals(order_num, total) VALUES (o, t);
UNTIL done END REPEAT;
CLOSE ordernumbers;
END;
SELECT * FROM ordertotals;
觸發(fā)器
MySQL5增加了對(duì)觸發(fā)器的支持。
想要某條語句(或某些語句)在事件發(fā)生時(shí)自動(dòng)執(zhí)行,這時(shí)就用到了觸發(fā)器。
觸發(fā)器:是MySQL響應(yīng)以下任意一條語句而自動(dòng)執(zhí)行的一條SQL語句(或位于BEGIN 和 END語句之間的一組語句 )。
- delete
- update
- insert
其他的語句不支持觸發(fā)器。
注意:只有表支持觸發(fā)器,視圖不支持(臨時(shí)表也不支持)。
創(chuàng)建觸發(fā)器:
在創(chuàng)建觸發(fā)器時(shí)的 4 部分:
- 唯一的觸發(fā)器名。(在表中唯一)建議:在數(shù)據(jù)庫中使觸發(fā)器名唯一。
- 觸發(fā)器關(guān)聯(lián)的表。
- 觸發(fā)器應(yīng)該響應(yīng)的事件(delete、update、insert)。
- 觸發(fā)器何時(shí)執(zhí)行after|before(處理之前或之后)。
CREATE TRIGGER newproduct // 創(chuàng)建名為newproduct的觸發(fā)器
AFTER INSERT ON products // 在insert語句成功執(zhí)行后執(zhí)行
FOR EACH ROW // 對(duì)每個(gè)插入行執(zhí)行
BEGIN
SELECT 'Product added' INTO @o; // 觸發(fā)器執(zhí)行的動(dòng)作
END;
SELECT @o; // 在插入之后查看該信息
每個(gè)表每個(gè)事件每次只允許有一個(gè)觸發(fā)器,因此,每個(gè)表最多支持6個(gè)觸發(fā)器(每條insert、update、delete的之前和之后)。
刪除觸發(fā)器:
DROP TRIGGER newproduct;
觸發(fā)器不能更新或覆蓋,為了修改一個(gè)觸發(fā)器,必須先刪除它,然后再重新創(chuàng)建。
使用觸發(fā)器:
事務(wù)處理
事務(wù)處理(transaction processing):可以用來維護(hù)數(shù)據(jù)庫的完整性,它保證成批的MySQL操作要么完全執(zhí)行,要么完全不執(zhí)行。
事務(wù)處理是一種機(jī)制。
在事務(wù)處理中的幾個(gè)術(shù)語:
事務(wù)(transaction):一組SQL語句。
回退(rollback):撤銷指定SQL語句的過程。
提交(commit):將未存儲(chǔ)的SQL語句結(jié)果寫入到數(shù)據(jù)庫。
保留點(diǎn)(savepoint):事務(wù)處理中設(shè)置的臨時(shí)占位符(placeholder),你可以對(duì)它發(fā)布回退(與回退整個(gè)事務(wù)處理不同,是部分的)。
控制事務(wù)處理:
管理事務(wù)處理的關(guān)鍵在于將SQL語句組分解為邏輯塊,并明確規(guī)定數(shù)據(jù)何時(shí)應(yīng)該回退,何時(shí)不應(yīng)該回退。
標(biāo)識(shí)事務(wù)開始:
START TRANSACTION;
使用回滾(rollback):
SELECT * FROM ordertotals;
START TRANSACTION;
DELETE FROM ordertotals;
SELECT * FROM ordertotals;
ROLLBACK ;
SELECT * FROM ordertotals;
rollback只能在一個(gè)事務(wù)處理內(nèi)使用(在執(zhí)行一條start transaction語句之后)。
注意:事務(wù)處理用來管理insert、update、delete,不能回退select語句。
也不能回退create或drop操作,在事務(wù)處理塊中可以有這兩條語句,但如果你執(zhí)行回退,他們不會(huì)被撤銷。
使用提交(commit):
在事務(wù)處理塊中,提交不是自動(dòng)進(jìn)行的,需要使用 commit 明確地提交。
START TRANSACTION ;
DELETE FROM orderitems WHERE order_num = 20010;
DELETE FROM orders WHERE order_num = 20010;
COMMIT ;
注意:當(dāng)commit 或 rollback 語句執(zhí)行后,事務(wù)會(huì)自動(dòng)關(guān)閉。
使用保留點(diǎn)(標(biāo)記):
為了支持回退部分事務(wù)處理,必須要在事務(wù)處理塊中合適的位置放置占位符(保留點(diǎn)),這樣,如果需要回退,可以回退到某個(gè)占位符。
創(chuàng)建占位符:
SAVEPOINT delete1;
-- 回滾到保留點(diǎn)
ROLLBACK TO delete1;
保留點(diǎn)標(biāo)識(shí)名要唯一。以便在回退時(shí)知道在何處。
釋放保留點(diǎn):
- 在執(zhí)行一條rollback 或 commit后自定釋放保留點(diǎn)。
- MySQL5以后可以使用 RELEASE SAVEPOINT delete1;明確地釋放保留點(diǎn)。
修改MySQL默認(rèn)的提交行為:
SET autocommit=0; // 不自動(dòng)提交
注意:autocommit標(biāo)志是針對(duì)每個(gè)連接的,而不是服務(wù)器。(標(biāo)志為連接專用)
MySQL的全球化和本地化
在MySQL的正常的數(shù)據(jù)庫活動(dòng)中,不需要操心太多的東西,使用何種字符局和校對(duì),決定在服務(wù)器、數(shù)據(jù)庫和表級(jí)進(jìn)行。
MySQL支持眾多的字符局。
SHOW CHARACTER SET
顯示所有可用的字符集以及每個(gè)字符集的描述和默認(rèn)校對(duì)。
SHOW COLLATION
顯示所有可用的校對(duì),以及他們適用的字符集。
_cs:表示區(qū)分大小寫。
_ci:表示不區(qū)分大小寫。
對(duì)整個(gè)表指定:
CREATE TABLE mytable(
column1 INT,
column2 VARCHAR(20)
) DEFAULT CHARACTER SET hebrew COLLATE hebrew_general_ci;
指定了一個(gè)字符集和一個(gè)校對(duì)順序。
對(duì)某個(gè)列指定:
CREATE TABLE mytable(
column1 INT,
column2 VARCHAR(20),
column3 VARCHAR(10) CHARACTER SET latinl COLLATE latinl_general_ci
) DEFAULT CHARACTER SET hebrew COLLATE hebrew_general_ci;
安全管理
訪問控制:管理訪問控制需要?jiǎng)?chuàng)建和管理用戶賬號(hào)。并賦予相應(yīng)的權(quán)限。
注意:在日常的工作中,決不能使用root,應(yīng)該創(chuàng)建一系列 的賬號(hào)來使用,有的用于管理,有的供用戶使用,有的用于開發(fā)者使用。
管理用戶:
MySQL用戶賬號(hào)和信息存儲(chǔ)在名為 mysql的數(shù)據(jù)庫中。
USE mysql;
SELECT user FROM user;
創(chuàng)建用戶賬號(hào):
CREATE USER user_name IDENTIFIED BY 'password';
重新命名用戶賬號(hào):(MySQL5支持)
RENAME USER old_name TO new_name;
刪除用戶賬號(hào):(刪除用戶及相關(guān)權(quán)限)
DROP USER user_name;
在MySQL5之前只能使用update來更新。
在5版本之前 DROP USER只能用來刪除用戶,不能刪除相關(guān)權(quán)限,需先使用 REVOKE 來刪除相關(guān)的權(quán)限,在刪除用戶。
更改指定用戶的口令:
SET PASSWORD FOR user_name = Password('password');
新口令必須傳遞到Password()函數(shù)進(jìn)行加密。
更改當(dāng)前用戶的口令:
SET PASSWORD = Password('password');
設(shè)置訪問權(quán)限:
在創(chuàng)建用戶賬號(hào)之后,接著給該賬號(hào)分配權(quán)限,否則登陸上mysql什么也干不了。
查看用戶所擁有的權(quán)限:
SHOW GRANTS FOR user_name;
設(shè)置權(quán)限:
GRANT SELECT ON db_name.* TO user_name;
這樣就賦予了用戶對(duì)該數(shù)據(jù)庫所有表的select權(quán)限。
GRANT要求至少要給出以下信息:
- 要授予的權(quán)限。
- 被授予訪問權(quán)限的數(shù)據(jù)庫或表。
- 用戶名。
撤銷特定的權(quán)限:
REVOKE SELECT ON db_name.* FROM user_name;
本撤銷的訪問權(quán)限必須存在,否則會(huì)出錯(cuò)。
多個(gè)授權(quán):(用逗號(hào)隔開)
GRANT SELECT, INSERT ON db_name.* TO user_name;
GRANT 和 REVOKE 可在幾個(gè)層次上控制訪問權(quán)限:
- 整個(gè)服務(wù)器,使用GRANT ALL 和 REVOKE ALL
- 整個(gè)數(shù)據(jù)庫,使用 ON databaseName.*
- 特定的表,使用 ON databaseName.tableName
- 特定的列
- 特定的存儲(chǔ)過程
MySQL的權(quán)限表:


