【MySQL】7:數據庫編程基礎

7.1 常量

常量:固定數據值、字面量、字面值、標量值
作用:參與運算或給變量賦值
種類:5種,包括:字符串、日期時間、數值、布爾、NULL。
其中:

字符串常量:用成對單引號“‘”或雙引號“””括起來的字符序列。

數值型常量:二進制、十進制與十六進制。

  1. 二進制常量如:b’1011’、B’1011’。
  2. 十進制常量,最常用,直接書寫,不需要定界符,如:3,-5,+3.14,123.7E-2
  3. 十六進制常量,需要使用前綴和單引號表示: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 用戶變量定義

會話用戶變量定義:

  1. SET @var1 = 值1 [, @var2 := 值2, … ]
  2. SELECT 值1 INTO @var1[, 值2 INTO @var2, … ]
  3. SELECT @var1 := 值1 [ , @var2 := 值2, … ]

需要注意以下幾點:

  1. 變量名@var1、@var2等必須以1個“@”開頭,可以由當前字符集的文字、數字、“.”、“_”和“$”等字符組成。
    當變量名中需要包含了一些特殊符號(如空格、#等)時,可以用雙引號、單引號或反引號(也叫勾號 ` 將整個變量名括起來。
  2. :=是賦值運算符,會產生結果集,在存儲函數中不能用來定義會話用戶變量。
  3. 值1、值2、… 可以是表達式或常量值。
  4. 會話用戶變量的賦值或設置,其形式與定義時完全相同。
    ————————————————————

局部變量定義:

DECLARE var1 [, var2] ... 數據類型[DEFAULT 默認值]

需要注意以下幾點:

  1. 局部變量的名稱不可以用“@”開頭。
  2. 缺省“[DEFAULT 默認值]”,則初始值爲NULL。
  3. “默認值”可以是表達式或常量。
  4. DECLARE只能用於BEGIN…END的開頭部分定義局部變量,
    作用範圍:只能在該BEGIN…END中使用。
  5. 存儲函數和存儲過程的形式參數也屬於局部變量。

7.2.2 系統變量

系統變量是MySQL用來跟蹤和記錄系統運行狀態的變量,用戶不能定義,但是可以訪問與修改,從而感知或影響系統。
被分爲全局系統變量和會話系統變量,都由MySQL系統定義並維護。

全局系統變量:

  1. 啓動時MySQL根據系統配置定義全局系統變量並初始化爲默認值(約393個全局系統變量)。
  2. 生存期從MySQL服務啓動時起,直到MySQL服務停止或重啓爲止。
  3. 作用範圍是整個系統,其值改變會影響整個系統。

會話系統變量:

  1. 生存期從客戶端連接MySQL服務開始,到連接斷開爲止。
  2. 連接開始時根據該瞬間的全局系統變量名稱、類型和值複製創建專屬於本連接的系統會話變量(約393個)。
    此外,還會創建專屬於本連接但不同於全局系統變量的其它變量(約12個系統會話變量不同於全局系統變量)。
  3. 會話系統變量的作用範圍僅僅侷限於本連接。
  4. 用戶更改專屬於本連接的會話系統變量的值,只會影響到本連接的運行狀態。

7.2.2.1 系統變量查看

SHOW [ GLOBAL | SESSION | LOCAL] VARIABLES [LIKE 模式字符串]
  1. GLOBAL限定查看全局系統變量,否則默認查看會話系統變量。
  2. “[LIKE 模式字符串]”查看特定系統變量,否則查看所有系統變量。
  3. 模式字符串中用“%”通配符表示0~多個字符。

• 系統變量名多數都以2個“@”開頭
• 用戶會話變量必須以1個“@”開頭
• 局部變量則不能以“@”開頭

7.2.3 設置變量

設置所有類型的變量值:
SET [ GLOBAL | [ SESSION | LOACAL| @@ | @ ]變量名1 =1
| @@global. | @@ [session. | @@local. | @@ | @]變量名1 =1

設置用戶變量值:
SELECT1 INTO [@]變量名1[ ,2 INTO [@]變量名2,]
SELECT [@ ] 變量名1 :=1[, @ ] 變量名2 :=2,]

需要特別指出的是以下幾點:

  1. 全局系統變量需要用GLOBAL或@@global.特別指出。
  2. LOCAL和SESSION是同義詞。
  3. 會話系統變量需要用SESSION、LOCAL、@@session.、@@local.
    或@@前綴。
  4. 會話用戶變量需要用“@”字符。
  5. 整個可選項[@@ global.|@@session. | @@local. |@@|@] 都缺省則改變局部變量的值。
  6. 可以用DEFAULT代替相應的“值”來恢復系統變量的默認值。

7.3 運算符與表達式

數據運算是計算機的基礎功能。

表達式是由常量、變量、運算符和函數構成的運算式。

靈活構建並求解表達式,是數據查詢、數據計算和變量賦值的基礎,更是判斷選擇和迭代循環的關鍵。

7.3.1 運算符種類

MySQL中運算符包括算術、比較、邏輯與位運算符四種。

算術運算符

符號 功能
+ 正號 或 加法運算
- 負號 或 減法運算
* 乘法
/
%、MOD 模運算,取整除後的餘數
DIV 整除,取商的整數部分

注意:

  1. 表達式中不能省略任何一個運算符
  2. +和-還可以表示取原數和取相反數運算
  3. +和-還可以用來計算日期,如:‘2019-06-19 22:55:02’ + interval 22 day
    #結果爲:‘2019-07-11 22:55:02’
  4. 算術表達式中的字符串會自動轉換爲數字進行運算,不能被轉換的轉換爲0

比較運算符

符號 功能
> 大於
< 小於
= 等於
>= 大於等於
<= 小於等於
!=<> 不等於
<=> 相等或都爲NULL
  1. 比較運算符的結果是True、1、0、False、NULL
  2. NULL參加的比較運算,除了“<=>”和 IS [NOT] NULL外,結果都是NULL。
  3. 字符串比較時(除非用BINARY關鍵字),默認不區分大小寫,還要先截掉字符串尾部所有的空格字符,再進行比較。
  4. [NOT] BETWEEN、 [NOT] IN、[NOT] LIKE、[NOT] REGEXP、IS [NOT] NULL 也被稱爲比較運算符。

邏輯運算符

符號 功能
!、NOT 非,否定,判斷指定條件是否不成立
&& 、AND 邏輯與,判斷是否兩個條件都成立
||、OR 邏輯或,判斷是否有條件成立
XOR 邏輯異或,判斷是否僅有一個條件成立

判斷選值運算符case也對多個條件進行運算,並根據條件的測試結果獲取
不同的結果,如下:

case
	when 條件1 then 表達式1
	when 條件2 then 表達式2else 表達式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. 只需要1個數據就可以運算的是一元運算符
  2. 關鍵字和一元運算符 !、+、-、~ 優先級最高
  3. 一般來說,各類運算符的優先次序如下:
    算術運算 > 位運算 > 比較運算 > 邏輯運算
  4. 構建表達式時,爲了保證準確性,應儘量使用小括號“( )”保證自
    己的設計意圖與系統的實際求解順序相一致,而不是依賴於優先級。

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 表達式
WHEN1 THEN S1;
[ WHEN2 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 [循環語句標籤] ;

功能:當循環條件成立時,一遍又一遍反覆執行循環體,
直到條件不成立爲止。

需要注意的是以下幾點:

  1. while之前的 “[循環語句標籤:]”和end while後的“[循環語句標籤]”一致。
  2. end while後以“;”結束。
  3. “循環語句 ;”可以是1條或多條MySQL語句,可包含leave和iterate語句。
  4. iterate語句作用:
    提前結束當前這一次循環體的執行。
    此時還在循環中,若循環條件還成立,會再次從頭執行循環體,
    直到條件不成立時循環語句才正常結束。
  5. 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 [循環語句標籤] ;

功能:當結束條件不成立時,一遍又一遍反覆執行循環體,
直到結束條件成立爲止。
  1. LOOP之前的 “[循環語句標籤:]”和END LOOP 之後的“[循環語
    句標籤]”必須一致。
  2. END LOOP後必須以“;”結束。
  3. “循環語句 ;”可以是1條或多條MySQL語句,可包含iterate語句。
  4. 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 [循環語句標籤] ;

功能:
當結束條件不成立時,一遍又一遍反覆執行循環體,
直到結束條件成立爲止。
  1. REPEAT之前的可選項“[循環語句標籤:]”和END REPEAT之後的“[循環語句標籤]”必須一致。
  2. END REPEAT後必須以“;”結束。
  3. “循環語句 ;”可以是1條或多條MySQL語句,可包含ITERATE和LEAVE語句。
  4. 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 $$
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章