SQL進(jìn)階1

1.w3School SQL簡單回顧

一.基礎(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;

二.高級

limit:(sql server:top,select top 50 percent * from person:查詢表中50%的記錄數(shù));
like(not like):配合通配符%,_使用;
通配符:配合like使用;
%:替代一個或多個字符
_:僅替代一個字符
[charlist]:字符列中的任意單一字符
[^charlist]/[!charlist]:不在字符列中的單一字符
slect * from person where name like '[!LW]%';
#查詢所有名字不以L,W開頭的人;
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): 如果表中有至少一個匹配,則返回行
LEFT JOIN: 即使右表中沒有匹配,也從左表返回所有的行
RIGHT JOIN: 即使左表中沒有匹配,也從右表返回所有的行
FULL JOIN: 只要其中一個表中存在匹配,就返回行

SELECT INTO用法(mysql當(dāng)前不支持該語法)

select *
into persons_backup [in internal_database]
from persons;
#將persons表中的數(shù)據(jù)全部復(fù)制到internal_database(省略則表示當(dāng)前庫)數(shù)據(jù)庫的persons_backup表中;

#實(shí)例1:將當(dāng)前數(shù)據(jù)庫的persons復(fù)制到backup數(shù)據(jù)庫的persons表
select * 
into persons in 'backup.mdb'
from persons;
#實(shí)例2:將person和order表中的數(shù)據(jù)匯總到數(shù)據(jù)庫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語法
create new_table 
from (
    select * 
    from old_table
    )

創(chuàng)建約束

#mysql語法
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語法
CREATE TABLE Persons
(
Id_P int NOT NULL UNIQUE, 注意:在這里
LastName varchar(255) NOT NULL,
FirstName varchar(255),
Address varchar(255),
City varchar(255)
)
#修改添加單個約束
ALTER TABLE Persons
ADD UNIQUE (Id_P)
#修改 添加多個約束
ALTER TABLE Persons
ADD CONSTRAINT uc_PersonID UNIQUE (Id_P,LastName)
#刪除約束,mysql語法
ALTER TABLE Persons
DROP INDEX uc_PersonID
#刪除約束,SQL Server / Oracle / MS Access語法
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語句

#添加列
alter table table_name
add column_name datatype;
#刪除列
alter table table_name
drop COLUMN column_name;
#如果不支持alter...drop..語法,則
alter table table_name
alter COLUMN column_name datatype;

date函數(shù)(mysql)

now():返回當(dāng)前日期和時間;
curdate():返回當(dāng)前日期;
curtime():返回當(dāng)前時間;
date():提取日期或日期/時間表達(dá)式的日期部分;
extract():返回日期/時間按的單獨(dú)部分
date_add():給日期添加指定的時間間隔;
date_sub():從日期減去指定的時間間隔;
datediff():返回兩個日期之間的天數(shù);
date_format():不同的格式顯示日期/時間;

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ù)一個或多個列對結(jié)果集進(jìn)行分組

#我們擁有下面這個 "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)在,我們希望查找每個客戶的總金額(總訂單)。
#我們想要使用 GROUP BY 語句對客戶進(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)鍵字無法與合計(jì)函數(shù)一起使用

SELECT Customer,SUM(OrderPrice) FROM Orders
GROUP BY Customer
HAVING SUM(OrderPrice)<2000

format語法:

SELECT FORMAT(column_name,format) FROM table_name;
#參數(shù) 描述
#column_name    必需。要格式化的字段。
#format 必需。規(guī)定格式。

TRUNCATE TABLE table_name

刪除表中的數(shù)據(jù)(只是刪除數(shù)據(jù))

2.mysql手冊學(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ù)庫/表等

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>#加載本地問價(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;#會刪除表關(guān)系
mysql>update pet set brith='1989-08-31' where name='bowser';
日期計(jì)算

要想確定每個寵物有多大,可以計(jì)算當(dāng)前日期的年和出生日期之間的差。如果當(dāng)前日期的日歷年比出生日期早,則減去一年。以下查詢顯示了每個寵物的出生日期、當(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ù)

YEAR( )
MONTH( )
DAYOFMONTH( )
QUARTER(date) :季度
MONTHNAME(date) :返回date是幾月(按英文名返回),如February
DAYNAME(date) :返回date是星期幾(按英文名返回),如Thursday

找出下個月生日的動物.如果當(dāng)前月份是12月,就有點(diǎn)復(fù)雜了

select name,brith from pet
where month(brith)=month(date_add(month(curdate(),interval 1 month));

#另一個方法是加1以得出當(dāng)前月份的下一個月(在使用取模函數(shù)(MOD)后,如果月份當(dāng)前值是12,則“回滾”到值0):
#MONTH返回在1和12之間的一個數(shù)字,MOD(something,12)返回在0和11之間的一個數(shù)字,因此必須在MOD( )以后加1
select name,brith from pet
where month(birth)=mod(month(curdate()),12) +1;                

模式匹配

%:匹配任意數(shù)目字符,包括領(lǐng)字符;
_:匹配任何單一字符;

MySQL提供的模式匹配的其它類型是使用擴(kuò)展正則表達(dá)式。當(dāng)你對這類模式進(jìn)行匹配測試時,使用REGEXP和NOT REGEXP操作符(或RLIKE和NOT RLIKE,它們是同義詞)。

‘.’匹配任何單個的字符。
“[...]”匹配在方括號內(nèi)的任何字符;例如,“[abc]”匹配“a”、“b”或“c”。為了命名字符的范圍,使用一個“-”?!癧a-z]”匹配任何字母,而“[0-9]”匹配任何數(shù)字;
“ * ”匹配零個或多個在它前面的字符。例如,“x*”匹配任何數(shù)量的“x”字符,“[0-9]*”匹配任何數(shù)量的數(shù)字,而“.*”匹配任何數(shù)量的任何字符;
#不區(qū)分大小寫的查找以“b”開頭的名字,使用“^”匹配名字的開始:
select * from pet where name regexp '^b';
#區(qū)分大小寫的查找以b開頭的名字
SELECT * FROM pet WHERE name REGEXP BINARY '^b';
#查找以fy結(jié)尾的名字
SELECT * FROM pet WHERE name REGEXP 'fy$';
#找出包含一個“w”的名字,使用以下查詢:
select * from pet where name regexp 'w';
#為了找出包含正好5個字符的名字,使用“^”和“$”匹配名字的開始和結(jié)尾,和5個“.”實(shí)例在兩者之間:
SELECT * FROM pet WHERE name REGEXP '^.{5}$';

2.獲取數(shù)據(jù)庫和表信息

#查看當(dāng)前使用數(shù)據(jù)庫
select database();
#查看表
show tables;
#查看表結(jié)構(gòu)
describe table_name;
#查看表的索引信息
show index from table_name;

3.批處理模式下使用SQL

#批處理基本語句
shell> mysql < batch-file
#Windows下運(yùn)行mysql,并且文件中有一些可以造成問題的特殊字符,可以這樣操作:
C:\> mysql -e "source batch-file"
#命令行上指定連接參數(shù),命令應(yīng)為 h:主機(jī)ip
shell> mysql -h host -u user -p < batch-file
shell> Enter password: ********
#如果你有一個產(chǎn)生多個輸出的查詢,你可以通過一個分頁器而不是盯著它翻屏到屏幕的頂端來運(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ù):找出最貴物品的編號、銷售商和價(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)最貴的物品( 例如每個的價(jià)格為19.95),LIMIT解決方案僅僅顯示其中一個!

任務(wù):每項(xiàng)物品的的最高價(jià)格是多少?

SELECT article, MAX(price) AS price
FROM   shop
GROUP BY article

任務(wù):對每項(xiàng)物品,找出最貴價(jià)格的物品的經(jīng)銷商。

SELECT article, dealer, price
FROM   shop s1
WHERE  price=(SELECT MAX(s2.price)
              FROM shop s2
              WHERE s1.article = s2.article);

使用用戶變量

例如,要找出價(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ù)類型及尺寸優(yōu)化

MySQL能更高效地在聲明具有相同類型和尺寸的列上使用索引;

如把兩個varchar類型的索引長度均設(shè)為20;

2.Analyze Table table_name:
MySQL 的Optimizer(優(yōu)化元件)在優(yōu)化SQL語句時,首先需要收集一些相關(guān)信息,其中就包括表的cardinality(可以翻譯為“散列程度”),它表示某個索引對應(yīng)的列包含多少個不同的值——如果cardinality大大少于數(shù)據(jù)的實(shí)際散列程度,那么索引就基本失效了。
我們可以使用SHOW INDEX語句來查看索引的散列程度
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);

這個時候就可以使用Analyze Table語句修復(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);
#需要注意的是,如果開啟了binlog,那么Analyze Table的結(jié)果也會寫入binlog,我們可以在analyze和table之間添加關(guān)鍵字local取消寫入。

Optimize Table

經(jīng)常更新數(shù)據(jù)的磁盤需要整理碎片,數(shù)據(jù)庫也是這樣,Optimize Table語句對MyISAM和InnoDB類型的表都有效。
如果表經(jīng)常更新,就應(yīng)當(dāng)定期運(yùn)行Optimize Table語句,保證效率。

與Analyze Table一樣,Optimize Table也可以使用local來取消寫入binlog。!

3.估計(jì)查詢性能
在大多數(shù)情況下,可以通過計(jì)算磁盤搜索來估計(jì)性能。對小的表,通常能在1次磁盤搜索中找到行(因?yàn)樗饕赡鼙痪彺?。對更大的表,可以使用B-樹索引進(jìn)行估計(jì),將需要log(row_count)/log(index_block_length/3 * 2/(index_length + data_pointer_length))+1次搜索才能找到行。

在MySQL中,索引塊通常是1024個字節(jié),數(shù)據(jù)指針通常是4個字節(jié),這對于有一個長度為3(中等整數(shù))的索引的500,000行的表,通過公式可以計(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ù)來找出行。

然而對于寫,將需要4次搜索請求(如上)來找到在哪兒存放新索引,并且通常需要2次搜索來更新這個索引并且寫入行。

注意,上述討論并不意味著應(yīng)用程序的性能將緩慢地以logN 退化!當(dāng)表格變得更大時,所有內(nèi)容緩存到OS或SQL服務(wù)器后,將僅僅或多或少地更慢。在數(shù)據(jù)變得太大不能緩存后,將逐漸變得更慢,直到應(yīng)用程序只能進(jìn)行磁盤搜索(以logN增加)。為了避免這個問題,隨數(shù)據(jù)增加而增加 鍵高速緩沖區(qū)大小。對于MyISAM表, 由key_buffer_size系統(tǒng)變量控制 鍵高速緩沖區(qū)大小。

4.索引合并優(yōu)化

4.1.索引合并交集

4.2.索引合并并集

4.3.索引合并排序并集

索引合并方法用于通過range掃描搜索行并將結(jié)果合成一個。合并會產(chǎn)生并集、交集或者正在進(jìn)行的掃描的交集的并集。

在EXPLAIN輸出中,該方法表現(xiàn)為type列內(nèi)的index_merge。在這種情況下,key列包含一列使用的索引,key_len包含這些索引的最長的關(guān)鍵元素。

注釋:索引合并優(yōu)化算法具有以下幾個已知缺陷:

` 如果可以對某些關(guān)鍵字進(jìn)行范圍掃描,則不考慮索引合并。例如,下面的查詢:

SELECT * FROM t1 WHERE (goodkey1 < 10 OR goodkey2 < 20) AND badkey < 30;

對于該查詢,可以有兩個方案:
1.    使用(goodkey1 < 10 OR goodkey2 <  20)條件進(jìn)行索引合并掃描。
2.    使用badkey < 30條件進(jìn)行范圍掃描。
然而,優(yōu)化器只考慮第2個方案。如果這不是你想要的,你可以通過使用IGNORE INDEX或FORCE INDEX讓優(yōu)化器考慮index_merge。下面的查詢使用索引合并執(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不能使用索引來解決ORDER BY,盡管它仍然使用索引來找到匹配WHERE子句的行。這些情況包括:

·對不同的關(guān)鍵字使用ORDER BY:
·   SELECT * FROM t1 ORDER BY key1, key2;
·對關(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;
·用于查詢行的關(guān)鍵字與ORDER BY中所使用的不相同:
·       SELECT * FROM t1 WHERE key2=constant ORDER BY key1;
·你正聯(lián)接許多表,并且ORDER BY中的列并不是全部來自第1個用于搜索行的非常量表。(這是EXPLAIN輸出中的沒有 const聯(lián)接類型的第1個表)。
·有不同的ORDER BY和GROUP BY表達(dá)式。
·使用的表索引的類型不能按順序保存行。例如,對于HEAP表的HASH索引情況即如此。
·使用的表索引的類型不能按順序保存行。例如,對于HEAP表的HASH索引情況即如此。

文件排序優(yōu)化不僅用于記錄排序關(guān)鍵字和行的位置,并且還記錄查詢需要的列。這樣可以避免兩次讀取行。文件排序算法的工作象這樣:
1.讀行匹配WHERE子句的行,如前面所示。
2.對于每個行,記錄構(gòu)成排序關(guān)鍵字和行位置的一系列值,并且記錄查詢需要的列。
3.根據(jù)排序關(guān)鍵字排序元組
4.按排序的順序檢索行,但直接從排序的元組讀取需要的列,而不是再一次訪問表。
                                            
如果想要增加ORDER BY的速度,首先看是否可以讓MySQL使用索引而不是額外的排序階段。如果不能,可以嘗試下面的策略:
·增加sort_buffer_size變量的大小。
·增加read_rnd_buffer_size變量的大小。

默認(rèn)情況下,MySQL排序所有GROUP BY col1,col2,...查詢的方法如同在查詢中指定ORDER BY col1,col2,...。如果顯式包括一個包含相同的列的ORDER BY子句,MySQL可以毫不減速地對它進(jìn)行優(yōu)化,盡管仍然進(jì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使用表掃描來解決查詢時使用的所有類型列。這通常在如下條件下發(fā)生:
·表很小,掃描表比查找關(guān)鍵字速度快。這對于少于10行并且行較短的表比較普遍。
·在ON或WHERE子句中沒有適用的索引列的約束。
·正用常量值比較索引列,并且MySQL已經(jīng)計(jì)算到(基于索引樹)常數(shù)覆蓋了表的很大部分并且表掃描將會比較快。參見7.2.4節(jié),“MySQL怎樣優(yōu)化WHERE子句”。
·你正通過另一個列使用一個低的集的勢的關(guān)鍵字(許多行匹配關(guān)鍵字)。在這種情況下,MySQL假設(shè)通過使用關(guān)鍵字   它可能會進(jìn)行許多關(guān)鍵字查找,表掃描將會更快。
  對于小表,表掃描通常合適。對于大表,嘗試下面的技巧以避免優(yōu)化器錯選了表掃描:
·使用ANALYZE TABLE tbl_name為掃描的表更新關(guān)鍵字分布。參見13.5.2.1節(jié),“ANALYZE TABLE語法”。
·對掃描的表使用FORCE INDEX告知MySQL,相對于使用給定的索引表掃描將非常耗時。參見13.2.7節(jié),“SELECT語法”。
·SELECT * FROM t1, t2 FORCE INDEX (index_for_column)
·WHERE t1.col_name=t2.col_name;
·用--max-seeks-for-key=1000選項(xiàng)啟動mysqld或使用SET max_seeks_for_key=1000告知優(yōu)化器假設(shè)關(guān)鍵字掃描不會超過1,000次關(guān)鍵字搜索。參見5.3.3節(jié),“服務(wù)器系統(tǒng)變量”。

4.存儲過程

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命令時,你應(yīng)該避免使用反斜杠(‘\’)字符,因?yàn)槟鞘荕ySQL的轉(zhuǎn)義字符。 

下列是一個例子,一個采用參數(shù)的函數(shù)使用一個SQL函數(shù)執(zhí)行一個操作,并返回結(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']
這個語句是一個MySQL的擴(kuò)展。它返回子程序的特征,如數(shù)據(jù)庫,名字,類型,創(chuàng)建者及創(chuàng)建和修改日期。如果沒有指定樣式,根據(jù)你使用的語句,所有存儲程序和所有存儲函數(shù)的信息都被列出。
SHOW FUNCTION STATUS LIKE 'hello'\G

存儲過程語法

1.CALL語句
2.BEGIN ... END復(fù)合語句;
3.DECLARE語句
4.存儲程序中的變量
4.1.DECLARE局部變量:DECLARE var_name[,...] type [DEFAULT value];
4.2.變量SET語句:SET var_name = expr [, var_name = expr] ...
4.3.SELECT ... INTO語句:SELECT col_name[,...] INTO var_name[,...] table_expr
如:SELECT id,data INTO x,y FROM test.t1 LIMIT 1;
重要: SQL變量名不能和列名一樣。如果SELECT ... INTO這樣的SQL語句包含一個對列的參考,并包含一個與列相同名字的局部變量,MySQL當(dāng)前把參考解釋為一個變量的名字。
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語句: OPEN cur1;
6.3. 光標(biāo)FETCH語句:FETCH cur1 INTO a, b;
6.4. 光標(biāo)CLOSE語句: 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語句
IF search_condition THEN statement_list
    [ELSEIF search_condition THEN statement_list] ...
    [ELSE statement_list]
END IF

7.2. CASE語句
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語句
[begin_label:] LOOP
    statement_list
END LOOP [end_label]

7.4. LEAVE語句
LEAVE label

7.5. ITERATE語句
ITERATE只可以出現(xiàn)在LOOP, REPEAT, 和WHILE語句內(nèi)。ITERATE意思為:“再次循環(huán)?!?

7.6. REPEAT語句
[begin_label:] REPEAT
    statement_list
UNTIL search_condition
END REPEAT [end_label]

7.7. WHILE語句
[begin_label:] WHILE search_condition DO
    statement_list
END WHILE [end_label]

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容