本文介紹MySQL數據庫中的變量、存儲過程、函數以及流程控制結構。這一塊是MySQL基礎中不會頻繁涉及的,但一旦使用就會極大提高工作效率的,特別是存儲過程
和函數
。
文章目錄
一、變量
MySQL中的變量主要分爲系統變量和自定義變量,系統變量又分爲全局變量和會話變量,自定義變量分爲用戶變量和局部變量。
(一)系統變量
系統變量是由系統定義
,不是用戶定義的,屬於服務器層面的變量。在系統變量中,又分爲全局變量和會話變量,全局變量需要添加global
關鍵字,針對於所有會話(連接)有效,但不能跨重啓(重啓服務器後失效,可通過修改配置文件進行設置);會話變量需要添加session
關鍵字,針對於當前會話(連接)有效;如果不寫標識,默認是會話變量。
系統變量的使用:
- 查看所有系統變量
show global |【session】variables; - 查看滿足條件的部分系統變量
show global |【session】 variables like ‘%char%’; - 查看指定的系統變量的值
select @@global. |【session.】系統變量名;
(注意是兩個@,如查自動提交變量:select @@global.autocommit; ) - 爲某個系統變量賦值
方式一:
set global |【session】系統變量名=值;
(如設置自動提交:set session autocommit = 1;)
方式二:
set @@global. |【session.】系統變量名=值;
(如設置不自動提交:set @@session.autocommit = 0;)
記住上面的使用語法就可以了,下面是對全局變量和會話變量的分別介紹。
1.全局變量
作用域:針對於所有會話(連接)有效,但不能跨重啓。
使用:
- 查看所有全局變量
SHOW GLOBAL VARIABLES; - 查看滿足條件的部分系統變量
SHOW GLOBAL VARIABLES LIKE ‘%char%’; - 查看指定的系統變量的值
SELECT @@global.autocommit;
- 爲某個系統變量賦值
方式一:
SET @@global.autocommit=0;
方式二:
SET GLOBAL autocommit=0;
2.會話變量
作用域:針對於當前會話(連接)有效。
使用:
- 查看所有會話變量
SHOW SESSION VARIABLES; - 查看滿足條件的部分會話變量
SHOW SESSION VARIABLES LIKE ‘%char%’; - 查看指定的會話變量的值
SELECT @@session.autocommit;
(其中session.可省略,即等效於SELECT @@autocommit;) - 爲某個會話變量賦值
方式一:
SET @@session.autocommit=0;
方式二:
SET SESSION autocommit=0;
(二)自定義變量
自定義變量由用戶自定義創建,以滿足開發過程的使用。
1.用戶變量
用戶變量針對於當前會話(連接)有效,作用域同於會話變量。使用時和Java中使用變量一樣,分三步:聲明、賦值、使用(有查看變量值、比較、運算等)
(1)聲明(MySQL中的用戶變量聲明時必須初始化)。寫法如下,必須在變量名前加@符號,支持的賦值符號爲=和 :=,但若使用select則必須使用 := 的寫法(因爲分不清是否爲比較運算)。
SET @變量名=值;
(由於等於號會有歧義,如將它與其他值進行比較,因此有下面 :=
的寫法)
SET @變量名:=值;
SELECT @變量名:=值;
(2)賦值(或者叫更新變量值)
方式一:
SET @變量名=值;
SET @變量名:=值;
SELECT @變量名:=值;
方式二:
SELECT 字段 INTO @變量名 FROM 表;
(3)查看變量的值
SELECT @變量名;
2.局部變量
局部變量僅僅在定義它的begin end塊中有效,並且需要在 begin end中的第一句話開始定義。
(1)聲明局部變量
DECLARE 變量名 類型 【DEFAULT 值】;
(2)賦值
方式一:
SET 局部變量名=值;
SET 局部變量名:=值;
SELECT 局部變量名:=值;
方式二:
SELECT 字段 INTO 局部變量名 FROM 表;
(3)查看變量的值
SELECT 局部變量名;
案例:聲明兩個變量,求和並打印
#用戶變量
SET @m=1;
SET @n=1;
SET @sum=@m+@n;
SELECT @sum;
#局部變量
DECLARE m INT DEFAULT 1;
DECLARE n INT DEFAULT 1;
DECLARE SUM INT;
SET SUM=m+n;
SELECT SUM;
用戶變量和局部變量的對比:
變量類型 | 作用域 | 定義位置 | 語法 |
---|---|---|---|
用戶變量 | 當前會話 | 會話的任何地方 | 加@符號,不用指定類型 |
局部變量 | 定義它的BEGIN END中 | BEGIN END的第一句話 | 一般不用加@,需要指定類型 |
二、存儲過程
MySQL中的存儲過程和函數類似於java中的方法,下面先介紹存儲過程。
1. 存儲過程介紹
含義:存儲過程是一組預先編譯好的SQL語句的集合,理解成批處理語句。
使用存儲過程的好處:
- 提高代碼的重用性
- 簡化操作
- 減少了編譯次數並且減少了和數據庫服務器的連接次數,提高了效率
創建語法:
DELIMITER 結束標記
CREATE PROCEDURE 存儲過程名(參數列表)
BEGIN
存儲過程體(一組合法的SQL語句)
END 結束標記
注意:
1、參數列表包含三部分:(參數模式 參數名 參數類型)
如:CREATE PROCEDURE myp1 (IN stuname VARCHAR(20)) …
參數模式:
in:該參數可以作爲輸入,也就是該參數需要調用方傳入值
out:該參數可以作爲輸出,也就是該參數可以作爲返回值
inout:該參數既可以作爲輸入又可以作爲輸出,也就是該參數既可以傳入值,又可以返回值
2、如果存儲過程體僅僅只有一句話,begin end可以省略
存儲過程體中的每條sql語句的結尾要求必須加分號。
存儲過程的結尾可以使用 delimiter 重新設置
語法:
delimiter 結束標記,如:delimiter $
調用語法:
CALL 存儲過程名(實參列表);
2. 存儲過程創建案例
案例1(空參列表的存儲過程):創建一個存儲過程,實現插入到admin表中五條記錄。
#創建
DELIMITER $
CREATE PROCEDURE myp1()
BEGIN
INSERT INTO admin(username,`password`)
VALUES('john1','0000'),('lily','0000'),('rose','0000'),('jack','0000'),('tom','0000');
END $
#調用
CALL myp1()$
#查看
select * from admin$
案例2(創建帶in模式參數的存儲過程):創建存儲過程實現,根據女神名查詢對應的男神信息。
#創建
CREATE PROCEDURE myp2(IN beautyName VARCHAR(20))
BEGIN
SELECT bo.*
FROM boys bo
RIGHT JOIN beauty b ON bo.id = b.boyfriend_id
WHERE b.name = beautyName;
END $
#調用
CALL myp2('柳巖')$
案例3(創建帶兩個in模式參數的存儲過程):創建存儲過程實現,判斷用戶是否登錄成功,即用戶名和密碼是否匹配。
#創建
CREATE PROCEDURE myp3(IN username VARCHAR(20),IN PASSWORD VARCHAR(20))
BEGIN
DECLARE result INT DEFAULT 0;#聲明並初始化
SELECT COUNT(*) INTO result#賦值
FROM admin
WHERE admin.username = username
AND admin.password = PASSWORD;
SELECT IF(result>0,'成功','失敗') 狀態;#使用
END $
#調用
CALL myp3('張飛','8888')$
案例4(創建帶out模式參數的存儲過程):根據輸入的女神名,返回對應的男神名和魅力值
#創建
CREATE PROCEDURE myp4(IN beautyName VARCHAR(20),OUT boyName VARCHAR(20),OUT usercp INT)
BEGIN
SELECT boys.boyname ,boys.usercp INTO boyname,usercp
FROM boys
RIGHT JOIN
beauty b ON b.boyfriend_id = boys.id
WHERE b.name=beautyName ;
END $
#調用
CALL myp4('小昭',@name,@cp)$
SELECT @name,@cp$
案例5(創建帶inout模式參數的存儲過程):傳入a和b兩個值,最終a和b都翻倍並返回
CREATE PROCEDURE myp5(INOUT a INT ,INOUT b INT)
BEGIN
SET a=a*2;
SET b=b*2;
END $
#調用
SET @m=10$ #需要先定義變量
SET @n=20$
CALL myp5(@m,@n)$
SELECT @m,@n$
3. 刪除存儲過程
語法:drop procedure 存儲過程名
存儲過程只能一次刪除一個,不支持同時刪除多個存儲過程。
DROP PROCEDURE p1;
DROP PROCEDURE p2,p3;#錯誤,不支持
4.查看存儲過程信息
語法:SHOW CREATE PROCEDURE myp1;
不能使用 DESC myp1;的方式
三、函數
1. 函數介紹
含義:函數和存儲過程一樣,是一組預先編譯好的SQL語句的集合,當然就具有以下的特點:
1、提高代碼的重用性
2、簡化操作
3、減少了編譯次數並且減少了和數據庫服務器的連接次數,提高了效率
函數和存儲過程的區別:
存儲過程:可以有0個返回,也可以有多個返回,適合做批量插入、批量更新
函數:有且僅有1 個返回,適合做處理數據後返回一個結果
創建語法:
CREATE FUNCTION 函數名(參數列表) RETURNS 返回類型
BEGIN
函數體
END
注意:
1、參數列表包含兩部分:參數名 參數類型
2、函數體:肯定會有return語句,如果沒有會報錯
如果return語句沒有放在函數體的最後不報錯,但不建議
3、函數體中僅有一句話,則可以省略begin end
4、使用 delimiter語句設置結束標記
調用語法:
SELECT 函數名(參數列表)
2.函數創建案例
案例1(無參有返回):返回公司的員工個數
#創建
CREATE FUNCTION myf1() RETURNS INT
BEGIN
DECLARE c INT DEFAULT 0;#定義局部變量
SELECT COUNT(*) INTO c#賦值
FROM employees;
RETURN c;
END $
#調用
SELECT myf1()$
案例2(有參有返回):根據員工名,返回它的工資
#創建
CREATE FUNCTION myf2(empName VARCHAR(20)) RETURNS DOUBLE
BEGIN
SET @sal=0;#定義用戶變量
SELECT salary INTO @sal #賦值
FROM employees
WHERE last_name = empName;
RETURN @sal;
END $
#調用
SELECT myf2('k_ing') $
案例3(有參有返回):根據部門名,返回該部門的平均工資
#創建
CREATE FUNCTION myf3(deptName VARCHAR(20)) RETURNS DOUBLE
BEGIN
DECLARE sal DOUBLE ;
SELECT AVG(salary) INTO sal
FROM employees e
JOIN departments d ON e.department_id = d.department_id
WHERE d.department_name = deptName;
RETURN sal;
END $
#調用
SELECT myf3('IT')$
3. 查看函數
語法:SHOW CREATE FUNCTION myf3;
4. 刪除函數
語法:DROP FUNCTION myf3;
四、流程控制結構
mysql中的流程控制結構包括:順序結構、分支結構與循環結構。
順序結構:程序從上往下依次執行
分支結構:程序從兩條或多條路徑中選擇一條去執行
循環結構:程序在滿足一定條件的基礎上,重複執行一段代碼
順序結構很好理解,程序從上往下執行即可,下面主要介紹分支結構和循環結構。
(一)分支結構
1. if函數
功能:實現雙分支
語法:if(條件,值1,值2)
執行順序:
如果條件成立,則返回值1,否則返回值2
應用在任何地方(begin end中或外面)
2. case結構
語法:
情況1:類似於java中的switch語句,一般用於實現等值判斷
case 變量|表達式|字段
when 要判斷的值 then 返回的值1或語句1;
when 要判斷的值 then 返回的值2或語句2;
…
else 返回的值n或語句n;
end case
情況2:類似於java中的多重if語句,一般用於實現區間判斷
case
when 要判斷的條件1 then 返回的值1或語句1;
when 要判斷的條件2 then 返回的值2或語句2;
…
else 返回的值n或語句n;
end case
case作爲表達式的情況:
case作爲獨立語句的情況:
特點:
1.可以作爲表達式,嵌套在其他語句中使用,可以放在任何地方,begin end 中或begin end的外面;可以作爲獨立的語句去使用,只能放在begin end中
2.如果when中的值滿足或條件成立,則執行對於功能的then後面的語句,並且結束case
如果都不滿足,則執行else中的語句或值
3.else可以省略,如果else省略了,並且所有when條件都不滿足,則返回null
3. if結構
功能:實現多重分支
語法:
if 條件1 then 語句1;
elseif 條件2 then 語句2;
…
【else 語句n;】
end if;
只能應用在begin end 中
案例1(使用存儲過程):創建存儲過程,根據傳入的成績,來顯示等級,如果成績爲90-100,顯示A,80-90,顯示B,60-80,顯示C,否則,顯示D
CREATE PROCEDURE test_case (IN score INT)
BEGIN
CASE
WHEN score>=90 AND score<=100 THEN SELECT 'A';
WHEN score>=80 THEN SELECT 'B';
WHEN score>=60 THEN SELECT 'C';
ELSE SELECT 'D';
END CASE;
END $
案例2(使用函數):創建函數,實現傳入成績,如果成績>90,返回A,如果成績>80,返回B,如果成績>60,返回C,否則返回D
CREATE FUNCTION test_if(score INT) RETURNS CHAR
BEGIN
IF score>=90 AND socre<=100 THEN RETURN 'A';
ELSEIF score>=80 THEN RETURN 'B';
ELSEIF score>=60 THEN RETURN 'C';
ELSE RETURN 'D';
END IF;
END $
(二)循環結構
介紹:
MySQL中的循環結構分三類:while、loop、repeat
循環控制:
iterate 類似於 continue,繼續,結束本次循環,繼續下一次
leave 類似於 break,跳出,結束當前所在的循環
語法:
while:
【標籤:】while 循環條件 do
循環體;
end while【 標籤】;
loop:
【標籤:】loop
循環體;
end loop 【標籤】;
repeat:
【標籤】repeat
循環體;
until 結束循環的條件
end repeat 【標籤】;
案例1(沒有添加循環控制語句):批量插入,根據次數插入到admin表中多條記錄
CREATE PROCEDURE pro_while1(IN insertCount INT)
BEGIN
DECLARE i INT DEFAULT 1;
WHILE i<=insertCount DO
INSERT INTO admin(username,`password`) VALUES(CONCAT('Rose',i),'666');
SET i=i+1;
END WHILE;
END $
案例2(添加leave語句):批量插入,根據次數插入到admin表中多條記錄,如果次數>20則停止
CREATE PROCEDURE test_while1(IN insertCount INT)
BEGIN
DECLARE i INT DEFAULT 1;
a:WHILE i<=insertCount DO
INSERT INTO admin(username,`password`) VALUES(CONCAT('xiaohua',i),'0000');
IF i>=20 THEN LEAVE a;
END IF;
SET i=i+1;
END WHILE a;
END $
案例3(添加iterate語句):批量插入,根據次數插入到admin表中多條記錄,只插入偶數次
CREATE PROCEDURE test_while1(IN insertCount INT)
BEGIN
DECLARE i INT DEFAULT 0;
a:WHILE i<=insertCount DO
SET i=i+1;
IF MOD(i,2)!=0 THEN ITERATE a;
END IF;
INSERT INTO admin(username,`password`) VALUES(CONCAT('xiaohua',i),'0000');
END WHILE a;
END $
案例4(流程控制經典案例):創建存儲過程,向 stringcontent 表中插入指定個數的隨機字符串,該表的結構如下:
CREATE TABLE stringcontent (
id INT PRIMARY KEY AUTO_INCREMENT,
content VARCHAR(20)
);
CREATE PROCEDURE test_randstr_insert(IN insertCount INT)
BEGIN
DECLARE i INT DEFAULT 1;
DECLARE str VARCHAR(26) DEFAULT 'abcdefghijklmnopqrstuvwxyz';
DECLARE startIndex INT DEFAULT 1;
DECLARE len INT DEFAULT 1;
WHILE i<=insertCount DO
SET len = FLOOR(RAND()*(20-startIndex+1) + 1);#產生一個隨機的整數,代表截取長度,1-(26-startIndex+1),此處定義的字符串最大長度爲20
SET startIndex=FLOOR(RAND()*26+1);#產生一個隨機整數,代表起始索引1-26
INSERT INTO stringcontent(content) VALUES(SUBSTR(str,startIndex,len));
SET i = i+1;#循環變量更新
END WHILE;
END $