7.1 常量
常量:固定數據值、字面量、字面值、標量值
作用:參與運算或給變量賦值
種類:5種,包括:字符串、日期時間、數值、布爾、NULL。
其中:
字符串常量:用成對單引號“‘”或雙引號“””括起來的字符序列。
數值型常量:二進制、十進制與十六進制。
- 二進制常量如:b’1011’、B’1011’。
- 十進制常量,最常用,直接書寫,不需要定界符,如:3,-5,+3.14,123.7E-2
- 十六進制常量,需要使用前綴和單引號表示:0x41、x’41’、X’41’
日期時間型:用單引號括起來,是有特殊格式的字符串。
格式:年-月-日[ 時:分:秒[.微秒] ]
• 年份取值爲1000-9999,月份取值1-12,日期取值1-31
• 方括號“[ ]” 表示可選項,具體值中不能出現方括號字符
• 省略“時:分:秒[.微秒]”只表示日期,可以精確到微秒級別
• 給TimeStamp列字段或變量賦值時會根據所處時區自動轉換,而且會忽略微秒部分,並要求年份只能取值1970-2037。
• “年-月-日”之間的分隔符“-”可以換爲“\”、“@”、“%”等
布爾型:只能表示True或False,1爲True,0爲False
NULL型:表示“未知”、“待定”、“沒有值”、“無數據”等意義,是一種無類型的值 ,但不同於0或空字符串的含義。
7.2 變量
變量分爲用戶變量和系統變量。
用戶變量:需要先定義再使用,定義變量的名稱、類型和初始值。
系統變量:系統所定義的變量,用戶可以訪問或修改,但是不能定義。
7.2.1 用戶變量
用戶變量又分爲:會話用戶變量和局部變量。
客戶端與MySQL服務建立連接後,可以定義會話用戶變量。
在用戶斷開連接之前,會話用戶變量一直起作用,但也只有該用戶的本次連接可用;連接斷開時會自動釋放會話用戶變量。
局部變量只在一段封裝的存儲程序內部起作用。在存儲程序調用結束釋放局部變量。
7.2.1.1 用戶變量定義
會話用戶變量定義:
SET @var1 = 值1 [, @var2 := 值2, … ]
SELECT 值1 INTO @var1[, 值2 INTO @var2, … ]
SELECT @var1 := 值1 [ , @var2 := 值2, … ]
需要注意以下幾點:
- 變量名@var1、@var2等必須以1個“@”開頭,可以由當前字符集的文字、數字、“.”、“_”和“$”等字符組成。
當變量名中需要包含了一些特殊符號(如空格、#等)時,可以用雙引號、單引號或反引號(也叫勾號 ` 將整個變量名括起來。 :=
是賦值運算符,會產生結果集,在存儲函數中不能用來定義會話用戶變量。- 值1、值2、… 可以是表達式或常量值。
- 會話用戶變量的賦值或設置,其形式與定義時完全相同。
————————————————————
局部變量定義:
DECLARE var1 [, var2] ... 數據類型[DEFAULT 默認值]
需要注意以下幾點:
- 局部變量的名稱不可以用“@”開頭。
- 缺省“[DEFAULT 默認值]”,則初始值爲NULL。
- “默認值”可以是表達式或常量。
- DECLARE只能用於BEGIN…END的開頭部分定義局部變量,
作用範圍:只能在該BEGIN…END中使用。 - 存儲函數和存儲過程的形式參數也屬於局部變量。
7.2.2 系統變量
系統變量是MySQL用來跟蹤和記錄系統運行狀態的變量,用戶不能定義,但是可以訪問與修改,從而感知或影響系統。
被分爲全局系統變量和會話系統變量,都由MySQL系統定義並維護。
全局系統變量:
- 啓動時MySQL根據系統配置定義全局系統變量並初始化爲默認值(約393個全局系統變量)。
- 生存期從MySQL服務啓動時起,直到MySQL服務停止或重啓爲止。
- 作用範圍是整個系統,其值改變會影響整個系統。
會話系統變量:
- 生存期從客戶端連接MySQL服務開始,到連接斷開爲止。
- 連接開始時根據該瞬間的全局系統變量名稱、類型和值複製創建專屬於本連接的系統會話變量(約393個)。
此外,還會創建專屬於本連接但不同於全局系統變量的其它變量(約12個系統會話變量不同於全局系統變量)。 - 會話系統變量的作用範圍僅僅侷限於本連接。
- 用戶更改專屬於本連接的會話系統變量的值,只會影響到本連接的運行狀態。
7.2.2.1 系統變量查看
SHOW [ GLOBAL | SESSION | LOCAL] VARIABLES [LIKE 模式字符串]
- GLOBAL限定查看全局系統變量,否則默認查看會話系統變量。
- “[LIKE 模式字符串]”查看特定系統變量,否則查看所有系統變量。
- 模式字符串中用“%”通配符表示0~多個字符。
• 系統變量名多數都以2個“@”開頭
• 用戶會話變量必須以1個“@”開頭
• 局部變量則不能以“@”開頭
7.2.3 設置變量
設置所有類型的變量值:
SET [ GLOBAL | [ SESSION | LOACAL| @@ | @ ]變量名1 = 值1
| @@global. | @@ [session. | @@local. | @@ | @]變量名1 = 值1
設置用戶變量值:
SELECT 值1 INTO [@]變量名1[ , 值2 INTO [@]變量名2, … ]
SELECT [@ ] 變量名1 := 值1[, @ ] 變量名2 := 值2, … ]
需要特別指出的是以下幾點:
- 全局系統變量需要用GLOBAL或@@global.特別指出。
- LOCAL和SESSION是同義詞。
- 會話系統變量需要用SESSION、LOCAL、@@session.、@@local.
或@@前綴。 - 會話用戶變量需要用“@”字符。
- 整個可選項[@@ global.|@@session. | @@local. |@@|@] 都缺省則改變局部變量的值。
- 可以用DEFAULT代替相應的“值”來恢復系統變量的默認值。
7.3 運算符與表達式
數據運算是計算機的基礎功能。
表達式是由常量、變量、運算符和函數構成的運算式。
靈活構建並求解表達式,是數據查詢、數據計算和變量賦值的基礎,更是判斷選擇和迭代循環的關鍵。
7.3.1 運算符種類
MySQL中運算符包括算術、比較、邏輯與位運算符四種。
算術運算符
符號 | 功能 |
---|---|
+ | 正號 或 加法運算 |
- | 負號 或 減法運算 |
* | 乘法 |
/ | 除 |
%、MOD | 模運算,取整除後的餘數 |
DIV | 整除,取商的整數部分 |
注意:
- 表達式中不能省略任何一個運算符
- +和-還可以表示取原數和取相反數運算
- +和-還可以用來計算日期,如:‘2019-06-19 22:55:02’ + interval 22 day
#結果爲:‘2019-07-11 22:55:02’ - 算術表達式中的字符串會自動轉換爲數字進行運算,不能被轉換的轉換爲0
比較運算符
符號 | 功能 |
---|---|
> | 大於 |
< | 小於 |
= | 等於 |
>= | 大於等於 |
<= | 小於等於 |
!=<> | 不等於 |
<=> | 相等或都爲NULL |
- 比較運算符的結果是True、1、0、False、NULL
- NULL參加的比較運算,除了“<=>”和 IS [NOT] NULL外,結果都是NULL。
- 字符串比較時(除非用BINARY關鍵字),默認不區分大小寫,還要先截掉字符串尾部所有的空格字符,再進行比較。
- [NOT] BETWEEN、 [NOT] IN、[NOT] LIKE、[NOT] REGEXP、IS [NOT] NULL 也被稱爲比較運算符。
邏輯運算符
符號 | 功能 |
---|---|
!、NOT | 非,否定,判斷指定條件是否不成立 |
&& 、AND | 邏輯與,判斷是否兩個條件都成立 |
|| 、OR |
邏輯或,判斷是否有條件成立 |
XOR | 邏輯異或,判斷是否僅有一個條件成立 |
判斷選值運算符case也對多個條件進行運算,並根據條件的測試結果獲取
不同的結果,如下:
case
when 條件1 then 表達式1
when 條件2 then 表達式2 …
else 表達式n
end
位運算符
符號 | 功能 | 舉例 |
---|---|---|
~ | 位非,逐位取反 | ~(b’1011’) #結果爲 (b’0100’) |
& | 按位與,相應位都爲1,結果位才爲1 | b’1011’ & b’1100’ #結果爲(b’1000’) |
| |
按位或,相應位至少1個爲1,結果位爲1 | b’1011’ | b’1001’ #結果爲(b’1011’) |
^ | 按位異或,相應位只能有1個爲1,結果位才爲1 | b’1011’ ^ b’1101’ #結果爲6(b’0110’) |
>> | 位右移 | b’1011’ >>2 #結果爲2 (b’0010’) |
<< | 位左移 | b’1011’ <<2 #結果爲44(b’101100’) |
7.3.2 運算符優先級
運算符 | 優先級 |
---|---|
INTERVAL | 1 |
BINARY、 COLLATE | 2 |
!(邏輯非) | 3 |
+(正)、–(負)、~(按位取反) | 4 |
*(乘)、/(除)、DIV(整除)、%或MOD(求餘、模運算) | 6 |
+(加)、–(減) | 7 |
<<(位左移)、 >>(位右移) | 8 |
&(按位與) | 9 |
| 按位或 |
10 |
=、>、<、>=、<=、<>、!= 、<=>、IS、LIKE、REGEXP、IN | 11 |
ALL、ANY、SOME、BETWEEN、CASE、WHEN、THEN、ELSE | 12 |
NOT(邏輯非) | 13 |
AND、&&(邏輯與) | 14 |
XOR(異或) | 15 |
OR、|| (邏輯或) |
16 |
=、:=(賦值) | 17 |
相關:
- 只需要1個數據就可以運算的是一元運算符
- 關鍵字和一元運算符 !、+、-、~ 優先級最高
- 一般來說,各類運算符的優先次序如下:
算術運算 > 位運算 > 比較運算 > 邏輯運算 - 構建表達式時,爲了保證準確性,應儘量使用小括號“( )”保證自
己的設計意圖與系統的實際求解順序相一致,而不是依賴於優先級。
7.4 條件選擇
條件結構分爲:
如何實現?
IF條件語句
IF 條件1 THEN S1;
[ ELSEIF 條件2 THEN S2; ]
...
[ ELSEIF 條件n THEN Sn; ]
[ELSE Sn+1;]
END IF;
CASE語句
CASE
WHEN 條件1 THEN S1;
[ WHEN 條件2 THEN S2; ]
...
[ WHEN 條件n THEN Sn; ]
[ELSE Sn+1;]
END CASE;
簡化CASE表達式
CASE 表達式
WHEN 值1 THEN S1;
[ WHEN 值2 THEN S2; ]
...
[ WHEN 值n THEN Sn; ]
[ ELSE Sn+1; ]
END CASE;
單項選擇實例:
mysql> use db1
Database changed
mysql> drop function if exists week_day1 $$
Query OK, 0 rows affected, 1 warning (0.01 sec)
mysql> set names gbk $$
Query OK, 0 rows affected (0.00 sec)
mysql> SET GLOBAL log_bin_trust_function_creators = 1 $$
Query OK, 0 rows affected (0.00 sec)
mysql> delimiter $$
mysql> create function week_day1(x tinyint)
-> returns char(3)
-> begin
-> declare wd char(3) default '工作日';
-> if x>5 then
-> set wd='雙休日';
-> end if;
->/* 可改用CASE語句如下實現:
CASE
WHEN x > 5 THEN SET wd = '雙休日’;
ELSE SET wd = '工作日';
END CASE;
*/
-> return wd;
-> end $$
Query OK, 0 rows affected (0.01 sec)
mysql> delimiter $$
mysql> select week_day1(2),week_day1(6) $$
+--------------+--------------+
| week_day1(2) | week_day1(6) |
+--------------+--------------+
| 工作日 | 雙休日 |
+--------------+--------------+
1 row in set (0.00 sec)
7.5 循環結構
循環結構:也叫重複結構,用來表達有條件、有規律、周而復始的數據處理功能。
循環體:需要規律性地重複執行的部分
循環條件:決定循環體是否執行、會執行幾遍、何時停止的表達式,
一般是比較表達式和邏輯表達式。
3種循環語句:WHILE、REPEAT和LOOP
7.5.1 WHILE循環
語法格式:
[循環語句標籤:] while 循環條件 do
循環語句 ;
# 可包含 leave[循環語句標籤] 和 iterate語句
end while [循環語句標籤] ;
功能:當循環條件成立時,一遍又一遍反覆執行循環體,
直到條件不成立爲止。
需要注意的是以下幾點:
- while之前的 “[循環語句標籤:]”和end while後的“[循環語句標籤]”一致。
- end while後以“;”結束。
- “循環語句 ;”可以是1條或多條MySQL語句,可包含leave和iterate語句。
iterate
語句作用:
提前結束當前這一次循環體的執行。
此時還在循環中,若循環條件還成立,會再次從頭執行循環體,
直到條件不成立時循環語句才正常結束。leave
語句用於在循環條件仍然成立時就結束循環語句,
此時已經跳出循環外,提前終結本循環。
循環實例:判斷是否是素數
mysql> delimiter $$
mysql> create function IsPrime(n int) returns int
-> begin
-> declare i int default 2;
-> declare y int default 1;
-> test:while i<n do
-> if n%i=0 then
-> set y=0;
-> leave test;
-> end if;
-> set i=i+1;
-> end while test;
-> return y;
-> end $$
Query OK, 0 rows affected (0.01 sec)
mysql> select IsPrime(2),IsPrime(5),IsPrime(9) $$
+------------+------------+------------+
| IsPrime(2) | IsPrime(5) | IsPrime(9) |
+------------+------------+------------+
| 1 | 1 | 0 |
+------------+------------+------------+
1 row in set (0.00 sec)
7.5.2 LOOP循環
語法格式:
[循環語句標籤:] LOOP
循環語句 ; #可包含 iterate語句
IF 結束條件 THEN
LEAVE [循環語句標籤] ;
END IF
END LOOP [循環語句標籤] ;
功能:當結束條件不成立時,一遍又一遍反覆執行循環體,
直到結束條件成立爲止。
- LOOP之前的 “[循環語句標籤:]”和END LOOP 之後的“[循環語
句標籤]”必須一致。 - END LOOP後必須以“;”結束。
- “循環語句 ;”可以是1條或多條MySQL語句,可包含iterate語句。
- LOOP循環本身沒有結束機制,必須使用LEAVE方可終止循環,而
LEAVE一般配合IF語句使用。
循環實例:LOOP素數檢查
mysql> delimiter $$
mysql> create function IsPrime1(n int) returns int
-> begin
-> declare i int default 2;
-> declare y int default 1;
-> if n=2 then return y;
-> end if;
-> test:LOOP
-> if n%i =0 then set y=0;
-> leave test;
-> end if;
-> set i=i+1;
-> if i>=n then leave test;
-> end if;
-> END LOOP test;
-> return y;
-> end $$
Query OK, 0 rows affected (0.01 sec)
7.5.3 REPEAT循環
語法格式:
[循環語句標籤:] REPEAT
循環語句 ; # 可包含ITERATE和LEAVE 語句
UNTIL 結束條件
END REPEAT [循環語句標籤] ;
功能:
當結束條件不成立時,一遍又一遍反覆執行循環體,
直到結束條件成立爲止。
- REPEAT之前的可選項“[循環語句標籤:]”和END REPEAT之後的“[循環語句標籤]”必須一致。
- END REPEAT後必須以“;”結束。
- “循環語句 ;”可以是1條或多條MySQL語句,可包含ITERATE和LEAVE語句。
- REPEAT循環本身就帶有結束循環的機制,LEAVE語句不是必須的。
循環實例:REPEAT判斷素數
mysql> delimiter $$
mysql> create function IsPrime2(n int) returns int
-> begin
-> declare i int default 2;declare y int default 1;if n=2 then return y;end if;
-> test:REPEAT
-> if n%i=0 then set y=0;leave test;end if;set i=i+1;
-> UNTIL i>=n
-> END REPEAT test;return y;
-> end $$
Query OK, 0 rows affected (0.01 sec)
mysql> select IsPrime2(7) $$
+-------------+
| IsPrime2(7) |
+-------------+
| 1 |
+-------------+
1 row in set (0.00 sec)
7.6 循環+遊標
循環是有條件、有規律地、反覆處理數據。需要不斷反覆處理的部分就是循環體,周而復始的關鍵就是循環條件。
• 用循環逐一處理多個記錄的思路:
先明確單條記錄要如何處理,將其作爲循環體。
接着把“所有記錄都處理完畢”作爲重複的先決條件。
然後選用合適的循環語句實現。
• 逐一地處理查詢到的記錄,需要用到遊標
遊標(Cursor)使用4步驟:定義、打開、取數據和關閉。
①遊標的定義,也叫遊標聲明:
確定需查詢的數據、指明數據的“查詢要求”:
declare 遊標名 cursor for select查詢語句;
②遊標的打開:
open 遊標名;執行遊標的“select查詢語句”,將結果存放到服務器內存中
③從遊標中取數據
fetch 遊標名 into 變量1 [, 變量2, … ];取結果集中一條記錄,存入into子句的1至多個變量中。
④關閉遊標:
close 遊標名;釋放查詢結果佔用的內存空間。
注:若遊標未關閉,在其所屬begin-end末尾也會自動關閉。
使用遊標的注意事項:
• 執行1次fetch命令只能取到1條記錄
• 1次select查詢往往都有多條記錄,要執行多次fetch。
如何用循環來控制fetch的執行次數呢?
方法1:根據結果集的條數確定。
方法2:用fetch取數據,取完了、無法再取時就會出錯並停止fetch。
使用實例:
mysql> delimiter $$
mysql> create function getCredits(no char(12) charset gbk) returns int
-> begin
-> declare s,m,score,credit,n int;
-> declare re cursor for
-> select a.score,b.credit
-> from choose a,course b
-> where a.course_id=b.course_id and student_id=no;
-> select count(*) into n
-> from choose a,course b
-> where a.course_id=b.course_id and student_id=no;
-> set s=0,m=1;
-> open re;
-> while m<=n do
-> fetch re into score,credit;
-> set m=m+1;
-> if score>=60 then set s=s+credit;
-> end if;
-> end while;
-> close re;
-> return s;
-> end $$