MySQL筆記(二):儲存結構、函式、流程控制
MySQL筆記(二):變數、儲存結構、函式、流程控制
變數
MySQL中 的變數分為系統變數和自定義變數,系統變數分為全域性變數和會話變數,自定義變數分為區域性變數和使用者變數
一、系統變數
作用域:
①全域性變數作用域:伺服器每次啟動將為所有的全域性變數賦初始值,針對於所有的會話(連線)有效,但不能跨重啟,如果想重啟之後依然生效就要手動修改配置檔案
②會話變數作用域:只針對當前會話有效,並且不能跨重啟
使用的語法:
①檢視所有的系統變數
show global|[session] variables;
②檢視滿足條件的系統變數
#檢視字符集 show global|[session] variables like '%char%';
③檢視指定的某個系統變數的值
select @@global|[session].系統變數名;
# 檢視當前會話的事務隔離級別
select @@tx_isolation;
④改變系統變數的值
# 方式一:
set global|[session] 系統變數 = 值;
# 方式二:
set @@global|[session].系統變數名 = 值;
注意:如果變數是全域性級別,則前面需要加上global;如果是會話級別,則加session,也可以不加,預設就是會話級別
二、自定義變數
(1)使用者變數
作用域:針對於當前會話(連線)有效,等同於會話變臉的作用域,可以應用在任何地方(即begin end之內或之位)
應用:
①宣告並初始化,宣告時必須進行初始化,可以使用SET或SELECT關鍵字和 =或:=操作符進行宣告和初始化操作,SELECT 關鍵字必須搭配 := 操作符使用
方式一:SET @使用者變數名 = 值;
方式二:SET @使用者變數名 := 值;
方式一:SELECT @使用者變數名 := 值;
②賦值,更新使用者變數的值
方式一:通過SET或SELETCT關鍵字,使用方式和宣告時一樣
SET @使用者變數名 = 值;
SET @使用者變數名 := 值;
SELECT @使用者變數名 := 值;
方式二:使用SELECT INTO關鍵字,欄位值必須是一個值
SELECT 欄位 INTO @變數名 FROM 表;
③使用,使用之前必須先宣告
檢視使用者變數的值:SELECT @使用者變數名;
# 宣告並初始化使用者變數 SET @count = 0; # 檢視使用者變數值 SELECT @count; # 更新使用者變數值 SELECT count(*) INTO @count FROM employees;
(2)區域性變數
作用域:僅僅在定義它的begin end中有效
應用:
①宣告區域性變數
方式一:只宣告,不賦值
DECLARE 區域性變數名 型別;
方式二:宣告並賦值
DEECLARE 區域性變數名 型別 DEFAULT 值;
②賦值
方式一:通過SET或SELECT,區域性變數名前面不需要加@
SET 區域性變數名 = 值;
SET 區域性變數名 := 值;
SELECT 區域性變數名 := 值;
方式二:通過SELECT INTO,區域性變數名前必須加上@
SELECT 欄位名 INTO @區域性變數名 FROM 表;
③使用
查詢變數名
SELECT 區域性變數名;
(三)使用者變數 PK 區域性變數
作用域 定義和使用的位置 語法 使用者變數 當前會話 當前會話的任何位置 必須加@符號,宣告時不用限定型別 區域性變數 僅僅在定義它的begin end中有效 只能在begin end中,且為第一句話 除SELECT INOT外不需要使用@符號,宣告時需要限定型別
(4)案例:
# 使用者變數
SET @m=1;
SET @n=2;
SET @sum = @m + @n;
SELECT @sum;
儲存過程和函式
儲存過程和函式類似於JAVA中的方法
一、儲存過程
含義:一組預先編譯好的SQL語句的集合,可以理解成批處理語句
優點:①提高程式碼的重用性
②簡化操作
③減少編譯次數和資料庫的連線次數,提高效率
應用場景:常用於增刪改資料,特別是一次性插入大量資料可以大大提高效率
應用:
①建立語法
CREATE PROCEDURE 儲存過程名(引數列表)
BEGIN
儲存過程體(一組合法的SQL語句)
END
注意事項:
引數列表中包含三部分:引數模式、引數名、引數型別
IN userId INT
引數模式:
IN:該引數可以作為輸入,也就是說該引數需要呼叫方在呼叫時傳入值
OUT:該引數可以作為輸出,也就是說該引數可以作為返回值
INOUT:該引數既可以作為輸入又可以作為輸出,也就是說該引數既需要傳入值也可以返回值
如果儲存過程體中僅僅只有一句話,BEGIN END可以省略
儲存過程體中的每條SQL語句的結尾必須加分號,儲存過程的結尾可以使用DELIMITER重新設定
語法:DELIMITER 結束標記;
# 以&作為儲存過程的結尾符 DELIMITER &;
②呼叫語法
CALL 儲存過程名(實參列表);
案例:
- 注意:儲存過程的命令只能在命令列中執行
# 修改結束標記為 $,後面不要加分號 DELIMITER $ # 案例一:儲存過程的引數列表中沒有引數 # 第一步:建立儲存過程 CREATE PROCEDURE p1() BEGIN INSERT INTO admin(`username`, `password`) VALUES ('user1', '123456'), ('user2', '123456'), ('user3', '123456'), ('user4', '123456'), ('user5', '123456'); # sql語句後面必須加上分號,表示該SQL語句的結束 END $ # 第二步:呼叫儲存過程 CALL p1()$ # 案例二:儲存過程的引數列表中有IN模式的引數 CREATE PROCEDURE p2(IN username VARCHAR(20), IN password VARCHAR(20)) BEGIN # 宣告區域性變數 DECLARE count INT DEFAULT 0; # 也可以在begin end中宣告使用者變數 # SET @sum = 0; SELECT count(*) INTO count FROM admin as a WHERE a.username = username # 引數可以直接使用,如果引數和表的欄位名重名,可以在表的欄位名前面加上表面進行限定 AND a.password = password; SELECT IF(count > 0, '登入成功', '登入失敗'); END $ CALL p2('user2', '123456')$ # 案例三:儲存過程的引數列表中有OUT模式的引數 CREATE PROCEDURE p3(IN userId INT, OUT username VARCHAR(20), OUT password VARCHAR(20)) BEGIN # 將a.username的值儲存在username變數中,將a.password儲存在password變數中 SELECT a.username, a.password INTO username, password FROM admin a WHERE a.id = userId; END $ # 儲存過程的實參列表中的使用者變數@username和@password可以不進行宣告,直接使用 CALL p3(1, @username, @password) $ SELECT @username, @password $ # 將結束標記還原成 ; DELIMITER ;
③刪除儲存過程
語法:DROP PROCEDURE 儲存過程名;
④檢視儲存過程的資訊
SHOW CREATE PROCEDURE 儲存過程名;
二、函式
函式的含義和優點與儲存過程一樣
函式與儲存過程的區別:儲存過程可以有0個返回或多個返回,而函式有且僅有一個返回;儲存過程適合做資料的批量插入和批量更新操作,而函式適合做處理資料後返回一個結果
①建立函式
語法:
CREATE FUNCTION 函式名(引數列表) RETURNS 返回型別
BEGIN
函式體
END
注意:
- 函式的引數列表包含兩個部分:引數名和引數型別
- 函式的函式體中肯定有RETURN語句,如果沒有會報錯;如果RETURN語句不是放在函式體的最後面也不會報錯,但是不建議這麼做
- 如果函式體中只有一條SQL語句,BEGIN END可以省略
- 也需要使用DELIMITER語句設定結束標記
②呼叫函式
語法:SELECT 函式名(引數列表);
③檢視函式資訊
語法:SHOW CREATE FUNCTION 函式名;
④刪除函式
語法:DROP FUNCTION 函式名;
案例:
DELIMITER $ # 案例一:無引數 CREATE FUNCTION f1() RETURNS INT BEGIN DECLARE count INT DEFAULT 0; SELECT COUNT(*) INTO count FROM admin; return count; END $ SELECT f1() $ # 案例二:有引數 CREATE FUNCTION f2(num1 FLOAT, num2 FLOAT) RETURNS FLOAT BEGIN DECLARE sum FLOAT DEFAULT 0; SET sum = num1 + num2; RETURN sum; END $ SELECT f2(1.0, 2.5); DELIMITER ;
流程控制結構
流程控制結構分為:順序結構、分支結構和迴圈結構
一、分支結構
(1)、IF函式
①功能:實現簡單雙分支
②作用域:可以作為表示式放在任何位置,即可以在begin end內和begin end外使用
③語法:
IF (條件表示式, 值1, 值2)
當條件表示式成立時返回值1,否則返回值2
④應用:
select IF(10>5, '10>5成立', '10>5不成立');
(2)、case結構
①功能:實現多分支
②作用域:可以放在任何位置。如果放在begin end 外面,作為表示式結合著其他語句使用;如果放在begin end 裡面,一般作為獨立的語句使用
③語法:
語法1:類似於switch
case 表示式或欄位
when 值1 then 語句1;
when 值2 then 語句2;
…
else 語句n;
end;語法2:
case
when 條件1 then 語句1;
when 條件2 then 語句2;
…
else 語句n;
end [case];④應用:
# 在begin end 外面 SELECT employee_id, last_name, salary, CASE salary WHEN salary>30000 then 'A級' WHEN salary>25000 THEN 'B級' WHEN salary>20000 THEN 'C級' WHEN salary>15000 THEN 'D級' WHEN salary>10000 THEN 'E級' ELSE 'F級' END as 'level' FROM employees # 在begin end 裡面 CREATE FUNCTION test_case(score FLOAT) RETURNS CHAR BEGIN DECLARE ch CHAR DEFAULT 'A'; CASE WHEN score>90 THEN SET ch='A'; WHEN score>80 THEN SET ch='B'; WHEN score>60 THEN SET ch='C'; ELSE SET ch='D'; END CASE; RETURN ch; END $
(3)、IF結構
①功能:類似於多重if
②作用域:只能應用在begin end 中
③語法:
if 條件1 then
語句1;
elseif 條件2 then 語句2;
…
else 語句n;
end if;④應用:
CREATE FUNCTION test_if(score FLOAT) RETURNS CHAR BEGIN DECLARE ch CHAR DEFAULT 'A'; IF score>90 THEN SET ch='A'; ELSEIF score>80 THEN SET ch='B'; ELSEIF score>60 THEN SET ch='C'; ELSE SET ch='D'; END IF; RETURN ch; END $
二、迴圈結構
流程控制
分類:iterate、leave
功能:
①iterate類似於 continue,繼續,結束本次迴圈,繼續下一次
② leave 類似於 break,跳出,結束當前所在的迴圈
迴圈結構
(一)while結構
①語法:標籤可以省略,當需要使用到迴圈控制時,前面的標籤才會用到
[標籤:]while 迴圈條件 do
迴圈體;
end while [標籤];
⑥應用:
# 向admin表中新增insertCount條資料 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 $
(二)、loop
①功能:一般用來模擬死迴圈
②語法:
[標籤:] loop
迴圈體;
end loop [標籤];
(三)repeat
①功能:相當於do …while,但是until中的條件是結束迴圈的條件
②語法:
[標籤:] repeat
迴圈體;
until 結束迴圈的條件
end repeat [標籤];
綜合案例
場景:admin表中只有三個欄位,分別是id(自增主鍵)、username、password,要求向admin表中新增指定數量的資料,username欄位和password欄位的值隨機生成,並且長度可以指定
原始碼:
DELIMITER $
DROP FUNCTION IF EXISTS generate_str_random;
/**
*功能:建立一個函式,生成指定長度的隨機字串
*引數:
*type是生成的字串型別,分別為username和password,兩種型別使用的字元庫不同,username型別生成的隨機字 *符串中只有字母,password型別生成的隨機字串中只有數字
*len是生成的隨機字串的長度
**/
CREATE FUNCTION generate_str_random(type VARCHAR(20), len INT) RETURNS VARCHAR(26)
BEGIN
# 儲存生成的隨機字串
DECLARE str VARCHAR(20) DEFAULT '';
# 生成使用者名稱的字元庫
DECLARE str1 VARCHAR(54) DEFAULT 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
# 生成密碼的字元庫
DECLARE str2 VARCHAR(10) DEFAULT '0123456789';
# 記錄迴圈次數
DECLARE i INT DEFAULT 0;
# 儲存每次隨機得到的字元
DECLARE s CHAR DEFAULT '';
# 儲存隨機生成的數字
DECLARE num INT DEFAULT 1;
IF type='username' THEN # 生成使用者名稱的隨機字串
# 迴圈,每次隨機獲取一個字元,將得到的字元加入帶字串中
WHILE i<len DO
# 生成一個隨機數,範圍為1到字元庫的長度,向上取整
SET num = CEIL(RAND() * LENGTH(str1));
# 從字元庫的num位置擷取一個字元
SET s = SUBSTR(str1, num, 1);
# 將隨機生產的字元拼接到str中
SET str = CONCAT(str, s);
SET i = i+1;
END WHILE;
ELSEIF type='password' THEN # 生成密碼的隨機字串
# 迴圈,每次隨機獲取一個字元,將得到的字元加入帶字串中
WHILE i<len DO
# 生成一個隨機數,範圍為1到字元庫的長度,向上取整
SET num = CEIL(RAND() * LENGTH(str2));
# 從字元庫的num位置擷取一個字元
SET s = SUBSTR(str2, num, 1);
# 將隨機生產的字元拼接到str中
SET str = CONCAT(str, s);
SET i = i+1;
END WHILE;
ELSE
SET str = '';
END IF;
return str;
END $
DROP PROCEDURE IF EXISTS insert_admin_user;
/**
*功能:建立一個儲存過程,用於向admin表中新增指定數量的使用者,使用者名稱和密碼隨機生成
*引數:
*num用於指定插入的資料量
**/
CREATE PROCEDURE insert_admin_user(IN num INT)
BEGIN
DECLARE i INT DEFAULT 0;
DECLARE len INT DEFAULT 6;
# 迴圈向admin表中加入資料
WHILE i < num DO
INSERT INTO admin(`username`, `password`) values(generate_str_random('username', len), generate_str_random('password', len));
SET i = i+1;
END WHILE;
END $
# 呼叫儲存過程,向admin表中插入1000條資料
CALL insert_admin_user(1000) $
DELIMITER ;