1.w3School SQL簡(jiǎn)單回顧
一.基礎(chǔ)
select
distict
where:=,<>,>,<,>=,<=,between,like
and & or:
order by : desc降序/asc升序(默認(rèn))
insert:insert into tableName values(v1,v2,...);
update:update tableName set col=newVal where col=value;
delete:delete from tableName where col=value;
二.高級(jí)
limit:(sql server:top,select top 50 percent * from person:查詢(xún)表中50%的記錄數(shù));
like(not like):配合通配符%,_使用;
通配符:配合like使用;
%:替代一個(gè)或多個(gè)字符
_:僅替代一個(gè)字符
[charlist]:字符列中的任意單一字符
[^charlist]/[!charlist]:不在字符列中的單一字符
slect * from person where name like '[!LW]%';
#查詢(xún)所有名字不以L,W開(kāi)頭的人;
in:
between...and...(not between...and...):
如下:
SELECT * FROM Persons
WHERE LastName
BETWEEN 'Adams' AND 'Carter';
以字母順序顯示介于 "Adams"(包括)和 "Carter"(不包括)之間的人
aliases:別名
select name as stu_name
from student
where age<10;
JOIN(INNER JOIN): 如果表中有至少一個(gè)匹配,則返回行
LEFT JOIN: 即使右表中沒(méi)有匹配,也從左表返回所有的行
RIGHT JOIN: 即使左表中沒(méi)有匹配,也從右表返回所有的行
FULL JOIN: 只要其中一個(gè)表中存在匹配,就返回行
SELECT INTO用法(mysql當(dāng)前不支持該語(yǔ)法)
select *
into persons_backup [in internal_database]
from persons;
#將persons表中的數(shù)據(jù)全部復(fù)制到internal_database(省略則表示當(dāng)前庫(kù))數(shù)據(jù)庫(kù)的persons_backup表中;
#實(shí)例1:將當(dāng)前數(shù)據(jù)庫(kù)的persons復(fù)制到backup數(shù)據(jù)庫(kù)的persons表
select *
into persons in 'backup.mdb'
from persons;
#實(shí)例2:將person和order表中的數(shù)據(jù)匯總到數(shù)據(jù)庫(kù)person_order_backup.mdb的person_order表中;
select person.lastName,order.orderNo
into person_order in 'person_order_backup.mdb'
from person
inner join order
on person.id=order.id;
#mysql語(yǔ)法
create new_table
from (
select *
from old_table
)
創(chuàng)建約束
#mysql語(yǔ)法
CREATE TABLE Persons
(
Id_P int NOT NULL,
LastName varchar(255) NOT NULL,
FirstName varchar(255),
Address varchar(255),
City varchar(255),
UNIQUE (Id_P) #放在后面指定一列
CONSTRAINT uc_PersonID UNIQUE (Id_P,LastName) #指定多列
)
#SQL Server / Oracle / MS Access語(yǔ)法
CREATE TABLE Persons
(
Id_P int NOT NULL UNIQUE, 注意:在這里
LastName varchar(255) NOT NULL,
FirstName varchar(255),
Address varchar(255),
City varchar(255)
)
#修改添加單個(gè)約束
ALTER TABLE Persons
ADD UNIQUE (Id_P)
#修改 添加多個(gè)約束
ALTER TABLE Persons
ADD CONSTRAINT uc_PersonID UNIQUE (Id_P,LastName)
#刪除約束,mysql語(yǔ)法
ALTER TABLE Persons
DROP INDEX uc_PersonID
#刪除約束,SQL Server / Oracle / MS Access語(yǔ)法
ALTER TABLE Persons
DROP CONSTRAINT uc_PersonID
創(chuàng)建索引
#降序創(chuàng)建索引
create index order_name_index
on table_name(order_name desc);
#刪除索引
alter table table_name drop index index_name;
alter語(yǔ)句
#添加列
alter table table_name
add column_name datatype;
#刪除列
alter table table_name
drop COLUMN column_name;
#如果不支持alter...drop..語(yǔ)法,則
alter table table_name
alter COLUMN column_name datatype;
date函數(shù)(mysql)
now():返回當(dāng)前日期和時(shí)間;
curdate():返回當(dāng)前日期;
curtime():返回當(dāng)前時(shí)間;
date():提取日期或日期/時(shí)間表達(dá)式的日期部分;
extract():返回日期/時(shí)間按的單獨(dú)部分
date_add():給日期添加指定的時(shí)間間隔;
date_sub():從日期減去指定的時(shí)間間隔;
datediff():返回兩個(gè)日期之間的天數(shù);
date_format():不同的格式顯示日期/時(shí)間;
DATE - 格式 YYYY-MM-DD
DATETIME - 格式: YYYY-MM-DD HH:MM:SS
TIMESTAMP - 格式: YYYY-MM-DD HH:MM:SS
YEAR - 格式 YYYY 或 YY
group by:用于結(jié)合合計(jì)函數(shù),根據(jù)一個(gè)或多個(gè)列對(duì)結(jié)果集進(jìn)行分組
#我們擁有下面這個(gè) "Orders" 表:
#O_Id OrderDate OrderPrice Customer
#1 2008/12/29 1000 Bush
#2 2008/11/23 1600 Carter
#3 2008/10/05 700 Bush
#4 2008/09/28 300 Bush
#5 2008/08/06 2000 Adams
#6 2008/07/21 100 Carter
#現(xiàn)在,我們希望查找每個(gè)客戶(hù)的總金額(總訂單)。
#我們想要使用 GROUP BY 語(yǔ)句對(duì)客戶(hù)進(jìn)行組合。
select Customer ,sum(OrderPrice)
from Orders
group by Customer;
#得到結(jié)果集如下:
#Customer SUM(OrderPrice)
#Bush 2000
#Carter 1700
#Adams 2000
having:在sql中增加having子句的原因是,where關(guān)鍵字無(wú)法與合計(jì)函數(shù)一起使用
SELECT Customer,SUM(OrderPrice) FROM Orders
GROUP BY Customer
HAVING SUM(OrderPrice)<2000
format語(yǔ)法:
SELECT FORMAT(column_name,format) FROM table_name;
#參數(shù) 描述
#column_name 必需。要格式化的字段。
#format 必需。規(guī)定格式。
TRUNCATE TABLE table_name
刪除表中的數(shù)據(jù)(只是刪除數(shù)據(jù))
2.mysql手冊(cè)學(xué)習(xí)補(bǔ)充
1.基礎(chǔ)
mysql>#查看版本和當(dāng)前日期
mysql>select version(),current_day;
mysql>select version;select now();select user();
1.1.創(chuàng)建數(shù)據(jù)庫(kù)/表等
mysql>show databasses;
mysql>create database dbName;
mysql>use dbName;
mysql>show tables;
mysql>create table pet (name varchar(20),owner varchar(20),sex char(10),birth DATE);
mysql>show tables;
mysql>describe pet
mysql>#加載本地問(wèn)價(jià)到mysql中
mysql>load data local infile '/path/pet.txt' into table pet lines terminated by '\r\n';
mysql>insert into pet values('puffball','diane','f','1999-03-30');
1.2.從表檢索信息
mysql>select * from pet;
mysql>delete from pet;#只刪除元組數(shù)據(jù)
mysql>drop from pet;#會(huì)刪除表關(guān)系
mysql>update pet set brith='1989-08-31' where name='bowser';
日期計(jì)算
要想確定每個(gè)寵物有多大,可以計(jì)算當(dāng)前日期的年和出生日期之間的差。如果當(dāng)前日期的日歷年比出生日期早,則減去一年。以下查詢(xún)顯示了每個(gè)寵物的出生日期、當(dāng)前日期和年齡數(shù)值的年數(shù)字。
select name,birth,curdate(),
(year(curdate())-year(brith)-(right(curdate())<right(birth)) as age
from pet
order by name;
#year()提取日期的年份;
#right()在這里提起日期的后5位進(jìn)行比較,比較的結(jié)果為0(false),1(true)
+----------+------------+------------+------+
| name | birth | CURDATE() | age |
+----------+------------+------------+------+
| Bowser | 1989-08-31 | 2003-08-19 | 13 |
| Buffy | 1989-05-13 | 2003-08-19 | 14 |
| Chirpy | 1998-09-11 | 2003-08-19 | 4 |
| Claws | 1994-03-17 | 2003-08-19 | 9 |
| Fang | 1990-08-27 | 2003-08-19 | 12 |
| Fluffy | 1993-02-04 | 2003-08-19 | 10 |
| Puffball | 1999-03-30 | 2003-08-19 | 4 |
| Slim | 1996-04-29 | 2003-08-19 | 7 |
| Whistler | 1997-12-09 | 2003-08-19 | 5 |
+----------+------------+------------+------+
提起時(shí)間函數(shù)
YEAR( )
MONTH( )
DAYOFMONTH( )
QUARTER(date) :季度
MONTHNAME(date) :返回date是幾月(按英文名返回),如February
DAYNAME(date) :返回date是星期幾(按英文名返回),如Thursday
找出下個(gè)月生日的動(dòng)物.如果當(dāng)前月份是12月,就有點(diǎn)復(fù)雜了
select name,brith from pet
where month(brith)=month(date_add(month(curdate(),interval 1 month));
#另一個(gè)方法是加1以得出當(dāng)前月份的下一個(gè)月(在使用取模函數(shù)(MOD)后,如果月份當(dāng)前值是12,則“回滾”到值0):
#MONTH返回在1和12之間的一個(gè)數(shù)字,MOD(something,12)返回在0和11之間的一個(gè)數(shù)字,因此必須在MOD( )以后加1
select name,brith from pet
where month(birth)=mod(month(curdate()),12) +1;
模式匹配
%:匹配任意數(shù)目字符,包括領(lǐng)字符;
_:匹配任何單一字符;
MySQL提供的模式匹配的其它類(lèi)型是使用擴(kuò)展正則表達(dá)式。當(dāng)你對(duì)這類(lèi)模式進(jìn)行匹配測(cè)試時(shí),使用REGEXP和NOT REGEXP操作符(或RLIKE和NOT RLIKE,它們是同義詞)。
‘.’匹配任何單個(gè)的字符。
“[...]”匹配在方括號(hào)內(nèi)的任何字符;例如,“[abc]”匹配“a”、“b”或“c”。為了命名字符的范圍,使用一個(gè)“-”?!癧a-z]”匹配任何字母,而“[0-9]”匹配任何數(shù)字;
“ * ”匹配零個(gè)或多個(gè)在它前面的字符。例如,“x*”匹配任何數(shù)量的“x”字符,“[0-9]*”匹配任何數(shù)量的數(shù)字,而“.*”匹配任何數(shù)量的任何字符;
#不區(qū)分大小寫(xiě)的查找以“b”開(kāi)頭的名字,使用“^”匹配名字的開(kāi)始:
select * from pet where name regexp '^b';
#區(qū)分大小寫(xiě)的查找以b開(kāi)頭的名字
SELECT * FROM pet WHERE name REGEXP BINARY '^b';
#查找以fy結(jié)尾的名字
SELECT * FROM pet WHERE name REGEXP 'fy$';
#找出包含一個(gè)“w”的名字,使用以下查詢(xún):
select * from pet where name regexp 'w';
#為了找出包含正好5個(gè)字符的名字,使用“^”和“$”匹配名字的開(kāi)始和結(jié)尾,和5個(gè)“.”實(shí)例在兩者之間:
SELECT * FROM pet WHERE name REGEXP '^.{5}$';
2.獲取數(shù)據(jù)庫(kù)和表信息
#查看當(dāng)前使用數(shù)據(jù)庫(kù)
select database();
#查看表
show tables;
#查看表結(jié)構(gòu)
describe table_name;
#查看表的索引信息
show index from table_name;
3.批處理模式下使用SQL
#批處理基本語(yǔ)句
shell> mysql < batch-file
#Windows下運(yùn)行mysql,并且文件中有一些可以造成問(wèn)題的特殊字符,可以這樣操作:
C:\> mysql -e "source batch-file"
#命令行上指定連接參數(shù),命令應(yīng)為 h:主機(jī)ip
shell> mysql -h host -u user -p < batch-file
shell> Enter password: ********
#如果你有一個(gè)產(chǎn)生多個(gè)輸出的查詢(xún),你可以通過(guò)一個(gè)分頁(yè)器而不是盯著它翻屏到屏幕的頂端來(lái)運(yùn)行輸出:
mysql < batch-file | more
#你可以捕捉文件中的輸出以便進(jìn)行進(jìn)一步的處理:
mysql < batch-file > mysql.out
#如果你想要在批模式中得到交互輸出格式,使用mysql -t。為了回顯以輸出被執(zhí)行的命令,使用mysql -vvv
#你還可以使用源代碼或 \.命令從mysql提示符運(yùn)行腳本:
mysql> source path/filename.sql;
mysql> \. path/filename.sql;
4.常用例子
任務(wù):找出最貴物品的編號(hào)、銷(xiāo)售商和價(jià)格
SELECT article, dealer, price
FROM shop
WHERE price=(SELECT MAX(price) FROM shop);
#或者
SELECT article, dealer, price
FROM shop
ORDER BY price DESC
LIMIT 1;
#注:如果有多項(xiàng)最貴的物品( 例如每個(gè)的價(jià)格為19.95),LIMIT解決方案僅僅顯示其中一個(gè)!
任務(wù):每項(xiàng)物品的的最高價(jià)格是多少?
SELECT article, MAX(price) AS price
FROM shop
GROUP BY article
任務(wù):對(duì)每項(xiàng)物品,找出最貴價(jià)格的物品的經(jīng)銷(xiāo)商。
SELECT article, dealer, price
FROM shop s1
WHERE price=(SELECT MAX(s2.price)
FROM shop s2
WHERE s1.article = s2.article);
使用用戶(hù)變量
例如,要找出價(jià)格最高或最低的物品的,其方法是:
mysql>select @min_price := min(price),@max_price := max(price);
mysql>select * from shop where price = @min_price or price = @max_price;
3.sql優(yōu)化
1.數(shù)據(jù)類(lèi)型及尺寸優(yōu)化
MySQL能更高效地在聲明具有相同類(lèi)型和尺寸的列上使用索引;
如把兩個(gè)varchar類(lèi)型的索引長(zhǎng)度均設(shè)為20;
2.Analyze Table table_name:
MySQL 的Optimizer(優(yōu)化元件)在優(yōu)化SQL語(yǔ)句時(shí),首先需要收集一些相關(guān)信息,其中就包括表的cardinality(可以翻譯為“散列程度”),它表示某個(gè)索引對(duì)應(yīng)的列包含多少個(gè)不同的值——如果cardinality大大少于數(shù)據(jù)的實(shí)際散列程度,那么索引就基本失效了。
我們可以使用SHOW INDEX語(yǔ)句來(lái)查看索引的散列程度
SHOW INDEX FROM PLAYERS;
mysql> show index from t_user_message\G;
*************************** 1. row ***************************
Table: t_user_message
Non_unique: 0
Key_name: PRIMARY
Seq_in_index: 1
Column_name: id
Collation: A
Cardinality: 15
Sub_part: NULL
Packed: NULL
Null:
Index_type: BTREE
Comment:
Index_comment:
1 row in set (0.00 sec);
這個(gè)時(shí)候就可以使用Analyze Table語(yǔ)句修復(fù)索引:
analyze table players;
再次show index from players;
*************************** 1. row ***************************
Table: t_user_message
Non_unique: 0
Key_name: PRIMARY
Seq_in_index: 1
Column_name: id
Collation: A
Cardinality: 1000
Sub_part: NULL
Packed: NULL
Null:
Index_type: BTREE
Comment:
Index_comment:
1 row in set (0.00 sec);
#需要注意的是,如果開(kāi)啟了binlog,那么Analyze Table的結(jié)果也會(huì)寫(xiě)入binlog,我們可以在analyze和table之間添加關(guān)鍵字local取消寫(xiě)入。
Optimize Table
經(jīng)常更新數(shù)據(jù)的磁盤(pán)需要整理碎片,數(shù)據(jù)庫(kù)也是這樣,Optimize Table語(yǔ)句對(duì)MyISAM和InnoDB類(lèi)型的表都有效。
如果表經(jīng)常更新,就應(yīng)當(dāng)定期運(yùn)行Optimize Table語(yǔ)句,保證效率。
與Analyze Table一樣,Optimize Table也可以使用local來(lái)取消寫(xiě)入binlog。!
3.估計(jì)查詢(xún)性能
在大多數(shù)情況下,可以通過(guò)計(jì)算磁盤(pán)搜索來(lái)估計(jì)性能。對(duì)小的表,通常能在1次磁盤(pán)搜索中找到行(因?yàn)樗饕赡鼙痪彺?。對(duì)更大的表,可以使用B-樹(shù)索引進(jìn)行估計(jì),將需要log(row_count)/log(index_block_length/3 * 2/(index_length + data_pointer_length))+1次搜索才能找到行。
在MySQL中,索引塊通常是1024個(gè)字節(jié),數(shù)據(jù)指針通常是4個(gè)字節(jié),這對(duì)于有一個(gè)長(zhǎng)度為3(中等整數(shù))的索引的500,000行的表,通過(guò)公式可以計(jì)算出log(500,000)/log(1024/3*2/(3+4))+1= 4次搜索。
上面的索引需要大約500,000 * 7 * 3/2 = 5.2MB,(假設(shè)典型情況下索引緩存區(qū)填充率為2/3),可以將大部分索引保存在內(nèi)存中,僅需要1-2調(diào)用從OS讀數(shù)據(jù)來(lái)找出行。
然而對(duì)于寫(xiě),將需要4次搜索請(qǐng)求(如上)來(lái)找到在哪兒存放新索引,并且通常需要2次搜索來(lái)更新這個(gè)索引并且寫(xiě)入行。
注意,上述討論并不意味著應(yīng)用程序的性能將緩慢地以logN 退化!當(dāng)表格變得更大時(shí),所有內(nèi)容緩存到OS或SQL服務(wù)器后,將僅僅或多或少地更慢。在數(shù)據(jù)變得太大不能緩存后,將逐漸變得更慢,直到應(yīng)用程序只能進(jìn)行磁盤(pán)搜索(以logN增加)。為了避免這個(gè)問(wèn)題,隨數(shù)據(jù)增加而增加 鍵高速緩沖區(qū)大小。對(duì)于MyISAM表, 由key_buffer_size系統(tǒng)變量控制 鍵高速緩沖區(qū)大小。
4.索引合并優(yōu)化
4.1.索引合并交集
4.2.索引合并并集
4.3.索引合并排序并集
索引合并方法用于通過(guò)range掃描搜索行并將結(jié)果合成一個(gè)。合并會(huì)產(chǎn)生并集、交集或者正在進(jìn)行的掃描的交集的并集。
在EXPLAIN輸出中,該方法表現(xiàn)為type列內(nèi)的index_merge。在這種情況下,key列包含一列使用的索引,key_len包含這些索引的最長(zhǎng)的關(guān)鍵元素。
注釋?zhuān)?/strong>索引合并優(yōu)化算法具有以下幾個(gè)已知缺陷:
` 如果可以對(duì)某些關(guān)鍵字進(jìn)行范圍掃描,則不考慮索引合并。例如,下面的查詢(xún):
SELECT * FROM t1 WHERE (goodkey1 < 10 OR goodkey2 < 20) AND badkey < 30;
對(duì)于該查詢(xún),可以有兩個(gè)方案:
1. 使用(goodkey1 < 10 OR goodkey2 < 20)條件進(jìn)行索引合并掃描。
2. 使用badkey < 30條件進(jìn)行范圍掃描。
然而,優(yōu)化器只考慮第2個(gè)方案。如果這不是你想要的,你可以通過(guò)使用IGNORE INDEX或FORCE INDEX讓優(yōu)化器考慮index_merge。下面的查詢(xún)使用索引合并執(zhí)行:
SELECT * FROM t1 FORCE INDEX(goodkey1,goodkey2)
WHERE (goodkey1 < 10 OR goodkey2 < 20) AND badkey < 30
SELECT * FROM t1 IGNORE INDEX(badkey)
WHERE (goodkey1 < 10 OR goodkey2 < 20) AND badkey < 30;
5.order by索引優(yōu)化
在某些情況下,MySQL不能使用索引來(lái)解決ORDER BY,盡管它仍然使用索引來(lái)找到匹配WHERE子句的行。這些情況包括:
·對(duì)不同的關(guān)鍵字使用ORDER BY:
· SELECT * FROM t1 ORDER BY key1, key2;
·對(duì)關(guān)鍵字的非連續(xù)元素使用ORDER BY:
· SELECT * FROM t1 WHERE key2=constant ORDER BY key_part2;
·混合ASC和DESC:
· SELECT * FROM t1 ORDER BY key_part1 DESC, key_part2 ASC;
·用于查詢(xún)行的關(guān)鍵字與ORDER BY中所使用的不相同:
· SELECT * FROM t1 WHERE key2=constant ORDER BY key1;
·你正聯(lián)接許多表,并且ORDER BY中的列并不是全部來(lái)自第1個(gè)用于搜索行的非常量表。(這是EXPLAIN輸出中的沒(méi)有 const聯(lián)接類(lèi)型的第1個(gè)表)。
·有不同的ORDER BY和GROUP BY表達(dá)式。
·使用的表索引的類(lèi)型不能按順序保存行。例如,對(duì)于HEAP表的HASH索引情況即如此。
·使用的表索引的類(lèi)型不能按順序保存行。例如,對(duì)于HEAP表的HASH索引情況即如此。
文件排序優(yōu)化不僅用于記錄排序關(guān)鍵字和行的位置,并且還記錄查詢(xún)需要的列。這樣可以避免兩次讀取行。文件排序算法的工作象這樣:
1.讀行匹配WHERE子句的行,如前面所示。
2.對(duì)于每個(gè)行,記錄構(gòu)成排序關(guān)鍵字和行位置的一系列值,并且記錄查詢(xún)需要的列。
3.根據(jù)排序關(guān)鍵字排序元組
4.按排序的順序檢索行,但直接從排序的元組讀取需要的列,而不是再一次訪問(wèn)表。
如果想要增加ORDER BY的速度,首先看是否可以讓MySQL使用索引而不是額外的排序階段。如果不能,可以嘗試下面的策略:
·增加sort_buffer_size變量的大小。
·增加read_rnd_buffer_size變量的大小。
默認(rèn)情況下,MySQL排序所有GROUP BY col1,col2,...查詢(xún)的方法如同在查詢(xún)中指定ORDER BY col1,col2,...。如果顯式包括一個(gè)包含相同的列的ORDER BY子句,MySQL可以毫不減速地對(duì)它進(jìn)行優(yōu)化,盡管仍然進(jìn)行排序。如果查詢(xún)包括GROUP BY但你想要避免排序結(jié)果的消耗,你可以指定ORDER BY NULL禁止排序。例如:
INSERT INTO foo
SELECT a, COUNT(*) FROM bar GROUP BY a ORDER BY NULL
6.GROUP BY優(yōu)化
6.1.松散索引掃面
6.2.緊湊索引掃描
7.如何避免表掃描
EXPLAIN的輸出顯示了當(dāng)MySQL使用表掃描來(lái)解決查詢(xún)時(shí)使用的所有類(lèi)型列。這通常在如下條件下發(fā)生:
·表很小,掃描表比查找關(guān)鍵字速度快。這對(duì)于少于10行并且行較短的表比較普遍。
·在ON或WHERE子句中沒(méi)有適用的索引列的約束。
·正用常量值比較索引列,并且MySQL已經(jīng)計(jì)算到(基于索引樹(shù))常數(shù)覆蓋了表的很大部分并且表掃描將會(huì)比較快。參見(jiàn)7.2.4節(jié),“MySQL怎樣優(yōu)化WHERE子句”。
·你正通過(guò)另一個(gè)列使用一個(gè)低的集的勢(shì)的關(guān)鍵字(許多行匹配關(guān)鍵字)。在這種情況下,MySQL假設(shè)通過(guò)使用關(guān)鍵字 它可能會(huì)進(jìn)行許多關(guān)鍵字查找,表掃描將會(huì)更快。
對(duì)于小表,表掃描通常合適。對(duì)于大表,嘗試下面的技巧以避免優(yōu)化器錯(cuò)選了表掃描:
·使用ANALYZE TABLE tbl_name為掃描的表更新關(guān)鍵字分布。參見(jiàn)13.5.2.1節(jié),“ANALYZE TABLE語(yǔ)法”。
·對(duì)掃描的表使用FORCE INDEX告知MySQL,相對(duì)于使用給定的索引表掃描將非常耗時(shí)。參見(jiàn)13.2.7節(jié),“SELECT語(yǔ)法”。
·SELECT * FROM t1, t2 FORCE INDEX (index_for_column)
·WHERE t1.col_name=t2.col_name;
·用--max-seeks-for-key=1000選項(xiàng)啟動(dòng)mysqld或使用SET max_seeks_for_key=1000告知優(yōu)化器假設(shè)關(guān)鍵字掃描不會(huì)超過(guò)1,000次關(guān)鍵字搜索。參見(jiàn)5.3.3節(jié),“服務(wù)器系統(tǒng)變量”。
4.存儲(chǔ)過(guò)程
mysql> delimiter //
mysql> CREATE PROCEDURE simpleproc (OUT param1 INT)
-> BEGIN
-> SELECT COUNT(*) INTO param1 FROM t;
-> END
-> //
Query OK, 0 rows affected (0.00 sec)
mysql> delimiter ;
mysql> CALL simpleproc(@a);
Query OK, 0 rows affected (0.00 sec)
mysql> SELECT @a;
+------+
| @a |
+------+
| 3 |
+------+
1 row in set (0.00 sec)
當(dāng)使用delimiter命令時(shí),你應(yīng)該避免使用反斜杠(‘\’)字符,因?yàn)槟鞘荕ySQL的轉(zhuǎn)義字符。
下列是一個(gè)例子,一個(gè)采用參數(shù)的函數(shù)使用一個(gè)SQL函數(shù)執(zhí)行一個(gè)操作,并返回結(jié)果:
mysql> delimiter //
mysql> CREATE FUNCTION hello (s CHAR(20)) RETURNS CHAR(50)
-> RETURN CONCAT('Hello, ',s,'!');
-> //
Query OK, 0 rows affected (0.00 sec)
mysql> delimiter ;
mysql> SELECT hello('world');
+----------------+
| hello('world') |
+----------------+
| Hello, world! |
+----------------+
1 row in set (0.00 sec)
SHOW PROCEDURE STATUS和SHOW FUNCTION STATUS
SHOW {PROCEDURE | FUNCTION} STATUS [LIKE 'pattern']
這個(gè)語(yǔ)句是一個(gè)MySQL的擴(kuò)展。它返回子程序的特征,如數(shù)據(jù)庫(kù),名字,類(lèi)型,創(chuàng)建者及創(chuàng)建和修改日期。如果沒(méi)有指定樣式,根據(jù)你使用的語(yǔ)句,所有存儲(chǔ)程序和所有存儲(chǔ)函數(shù)的信息都被列出。
SHOW FUNCTION STATUS LIKE 'hello'\G
存儲(chǔ)過(guò)程語(yǔ)法
1.CALL語(yǔ)句
2.BEGIN ... END復(fù)合語(yǔ)句;
3.DECLARE語(yǔ)句
4.存儲(chǔ)程序中的變量
4.1.DECLARE局部變量:DECLARE var_name[,...] type [DEFAULT value];
4.2.變量SET語(yǔ)句:SET var_name = expr [, var_name = expr] ...
4.3.SELECT ... INTO語(yǔ)句:SELECT col_name[,...] INTO var_name[,...] table_expr
如:SELECT id,data INTO x,y FROM test.t1 LIMIT 1;
重要: SQL變量名不能和列名一樣。如果SELECT ... INTO這樣的SQL語(yǔ)句包含一個(gè)對(duì)列的參考,并包含一個(gè)與列相同名字的局部變量,MySQL當(dāng)前把參考解釋為一個(gè)變量的名字。
5.條件和處理程序
5.1. DECLARE條件
5.2. DECLARE處理程序
6.光標(biāo)
6.1.聲明光標(biāo):DECLARE cur1 CURSOR FOR SELECT id,data FROM test.t1;
6.2. 光標(biāo)OPEN語(yǔ)句: OPEN cur1;
6.3. 光標(biāo)FETCH語(yǔ)句:FETCH cur1 INTO a, b;
6.4. 光標(biāo)CLOSE語(yǔ)句: CLOSE cur1;
CREATE PROCEDURE curdemo()
BEGIN
DECLARE done INT DEFAULT 0;
DECLARE a CHAR(16);
DECLARE b,c INT;
DECLARE cur1 CURSOR FOR SELECT id,data FROM test.t1;
DECLARE cur2 CURSOR FOR SELECT i FROM test.t2;
DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET done = 1;
OPEN cur1;
OPEN cur2;
REPEAT
FETCH cur1 INTO a, b;
FETCH cur2 INTO c;
IF NOT done THEN
IF b < c THEN
INSERT INTO test.t3 VALUES (a,b);
ELSE
INSERT INTO test.t3 VALUES (a,c);
END IF;
END IF;
UNTIL done END REPEAT;
CLOSE cur1;
CLOSE cur2;
END
7.流程控制構(gòu)造
7.1. IF語(yǔ)句
IF search_condition THEN statement_list
[ELSEIF search_condition THEN statement_list] ...
[ELSE statement_list]
END IF
7.2. CASE語(yǔ)句
CASE case_value
WHEN when_value THEN statement_list
[WHEN when_value THEN statement_list] ...
[ELSE statement_list]
END CASE
Or: 或者:
CASE
WHEN search_condition THEN statement_list
[WHEN search_condition THEN statement_list] ...
[ELSE statement_list]
END CASE
7.3. LOOP語(yǔ)句
[begin_label:] LOOP
statement_list
END LOOP [end_label]
7.4. LEAVE語(yǔ)句
LEAVE label
7.5. ITERATE語(yǔ)句
ITERATE只可以出現(xiàn)在LOOP, REPEAT, 和WHILE語(yǔ)句內(nèi)。ITERATE意思為:“再次循環(huán)?!?
7.6. REPEAT語(yǔ)句
[begin_label:] REPEAT
statement_list
UNTIL search_condition
END REPEAT [end_label]
7.7. WHILE語(yǔ)句
[begin_label:] WHILE search_condition DO
statement_list
END WHILE [end_label]