MySQL 資料庫(六)—— 資料庫程式設計:資料庫的變數、資料庫控制語句、資料庫函式、儲存過程、觸發器等
文章目錄
一、資料庫的變數
1、系統變數
(1)系統變數顧名思義就是系統提供的變數,屬於伺服器層面上的,存放在資料庫服務端,用於設定整個資料庫的變數,如 autocommit。
如果是全域性級別,則需要新增 GLOBAL,如果是會話級別,則新增 SESSION,如果不寫則預設 SESSION。
作用域:伺服器每次啟動將為所有的全域性變數賦初始值,針對於所有的會話(連線)有效,但不能跨重啟(即修改過的系統變數在重啟會恢復預設值)。
(2)語法:
① 檢視所有的系統變數
SHOW GLOBAL VARIABLES; -- 全域性系統變數
② 檢視滿足條件的部分系統變數
SHOW GLOBAL VARIABLES like '%char%';
③ 檢視指定的某個系統變數的值
SELECT @@系統變數名;
SELECT @@GLOBAL.系統變數名;
-- eg:
SELECT @@GLOBAL.autocommit;
④ 設定系統變數名(修改系統變數)
系統變數會控制所有的使用者,一旦修改了系統變數,那麼所有的連線都將修改。
SET 系統變數名 := 值;
第二種方式:這種修改能夠作用到整個資料庫服務端的系統變數,但使用這種方式修改, 當前連線的客戶端不會起作用,只有重新連線的客戶端才會起作用。
SET @@GLOBAL.系統變數 = 值;
--eg:
SET @@GLOBAL.autocommit = 0;
2、會話變數
(1)當前連線的會話起作用。
作用域:僅僅針對於當前會話(連線)有效。
(2)語法
① 檢視所有會話變數
SHOW VARIABLES;
SHOW SESSION VARIABLES;
② 檢視部分會話變數
SHOW VARIABLES LIKE '%char%'; SHOW SESSION VARIABLES LIKE '%char%';
③ 檢視指定的某個會話變數
SET @@會話變數名;
SET @@SESSION.會話變數;
④ 為某個會話變數賦值(修改會話變數值)
SET @@會話變數 = 值;
SET @@SESSION.會話變數 = 值;
SET SESSION 會話變數名 = 值;
3、區域性變數
(1)只能作用域區域的變數,作用域是 begin 和 end 區域之間,並且使用 declare 關鍵字進行定義
(2)步驟
① 宣告
DECLARE 變數名 型別;
DECLARE 變數名 型別; DEFAULT 值;
DECLARE i INT DEFAULT 0 ;
② 賦值(修改)
方式一
SET @區域性變數名 = 值;
SET @區域性變數名 := 值;
SELECT @區域性變數名 := 值;
方式二
SELECT 欄位 INTO @區域性變數名 FROM 表;
③ 使用(檢視)
SELECT @區域性變數名;
4、自定義變數
(1)使用者自己定義的變數,不是系統的,針對於當前會話有效,等同於會話變數的作用域,但是可以應用在任何位置,begin和end裡面可以,外面也可以
(2)使用步驟
① 宣告並初始化
SET @使用者變數名 = 值;
SET @使用者變數名 := 值;
SELECT @使用者變數名 := 值;
因為 " =" 容易有歧義,所以MySQL又推薦另一種寫法,":=" 。
② 賦值(修改使用者變數的值)
第一種:
SET @使用者變數名 = 值;
SET @使用者變數名 := 值;
SELECT @使用者變數名 := 值;
第二種:
SELECT 欄位 INTO @使用者變數名 FROM 表;
③ 使用(檢視使用者變數的值)
SELECT @使用者變數名;
二、控制語句——分支、迴圈
1、IF 分支
(1)語法:
IF 條件1 THEN
執行語句1;
ELSE IF 條件2 THEN
執行語句2;
...
ELSE
執行語句n;
END IF;
(2)Demo:根據傳入的分數判斷成績等級
-- 根據傳入的分數判斷成績等級
delimiter &&
CREATE FUNCTION method5(score INT) RETURNS CHAR
BEGIN
IF score >= 90 AND score <= 100 THEN
RETURN 'A';
ELSEIF score >= 80 THEN
RETURN 'B';
ELSEIF score >= 60 THEN
RETURN 'C';
ELSE
RETURN 'D';
END IF;
END
&&
delimiter ;
SELECT method5(85);
2、CASE 分支
(1)類似於java中的switch,一般用於實現等值判斷。
語法:
CASE 變數|表示式|欄位
WHEN 值1 THEN 返回的值1或執行語句1;
WHEN 值2 THEN 返回的值2執行語句2;
...
ELSE 執行語句n;
END CASE;
是返回值的話不用加分號。
CASE 變數|表示式|欄位
WHEN 值1 THEN 返回的值1
WHEN 值2 THEN 返回的值2
...
ELSE 執行語句n
END
(2)類似於java中的多重if語句,一般用於實現區間判斷。
語法:
CASE
WHEN 條件1 THEN 返回的值1執行語句1;
WHEN 條件2 THEN 返回的值2執行語句2;
...
ELSE 執行語句n;
END CASE;
注意:
- 可以作為表示式,巢狀在其他語句中,可以放在任何位置,BEGIN和END裡面和外面。可以作為獨立的語句,只能放置BEGIN和END裡面使用。
- 如上述語法中,如果是執行語句,滿足條件並執行對應語句之後就跳出整個結構,不滿足條件則繼續往下執行。
- 如果WHEN中的值滿足或條件成立,則執行對應的THEN後面的語句,並且結束CASE,如果都不滿足,則執行ELSE中的語句。
- ELSE可以省略,如果省略了,並且所有的WHEN的條件都不滿足,則返回NULL。
(3)Demo:根據傳入的分數判斷成績等級
-- 根據傳入的分數判斷成績等級
delimiter &&
CREATE PROCEDURE method4(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
&&
delimiter ;
CALL method4(85);
3、WHILE 迴圈
(1)分類
WHILE、LOOP、REPEAT
(2)迴圈控制
① leave: 離開迴圈,相當於java中的 break,結束整個迴圈
② iterate:持續迭代,相當於java中的 continue,結束本次迴圈繼續下次迴圈
(3)語法:
① WHILE 的語法
[標記:] WHILE 條件判斷 DO
迴圈語句;
END WHILE [標記];
Demo:儲存過程實現100-500之間的累加
-- 儲存過程實現100-500之間的累加
delimiter &&
CREATE PROCEDURE method2()
BEGIN
DECLARE sum INT DEFAULT 0;
DECLARE i INT DEFAULT 100;
WHILE i <= 500 DO
SET sum := sum + i;
SET i := i + 1;
END WHILE;
SELECT sum;
END
&&
delimiter ;
-- 查詢儲存過程
SHOW PROCEDURE STATUS;
-- 呼叫函式檢視結果
CALL method2();
② LOOP的語法
[標記:] LOOP
迴圈語句;
END LOOP [標記];
可以用來模擬簡單的死迴圈
③ REPEAT的語法
[標記:] REPEAT
迴圈語句;
UNTIL 結束迴圈的條件
END REPEAT [標記];
Demo1:計算100以內的偶數和
-- 計算100以內的偶數和
-- 方法一
delimiter &&
CREATE FUNCTION method() RETURNS INT
BEGIN
DECLARE sum INT DEFAULT 0;
DECLARE i INT DEFAULT 0;
-- WHILE 迴圈進行迴圈
p1:WHILE i <= 100 DO
-- IF 分支進行判斷
IF i % 2 = 0 THEN
SET sum := sum + i;
END IF;
SET i := i + 1;
END WHILE p1;
RETURN sum;
END;
&&
delimiter ;
-- 呼叫函式檢視結果
SELECT method();
-- 方法二
delimiter &&
CREATE FUNCTION method1() RETURNS INT
BEGIN
DECLARE i INT DEFAULT 0;
DECLARE sum INT DEFAULT 0;
p1:WHILE i < 100 DO
SET sum := sum + i;
if i % 2 <> 0 THEN
-- 重新從p1出開始迭代
ITERATE p1;
END IF;
SET sum := sum + i;
END WHILE p1;
RETURN sum;
END
&&
delimiter ;
-- 呼叫函式檢視結果
SELECT method1();
Demo2:計算x的y次方
-- 計算x的y次方
delimiter &&
CREATE PROCEDURE method3()
BEGIN
DECLARE x INT DEFAULT 2;
DECLARE y INT DEFAULT 4;
DECLARE i INT DEFAULT 0;
DECLARE res DOUBLE DEFAULT 1.0;
IF y > 0 THEN
p1:WHILE i < y DO
SET res = res * x;
SET i = i + 1;
END WHILE p1;
END IF;
IF y < 0 then
set y = y * (-1);
p2:WHILE i < y DO
SET res = res * x;
SET i = i + 1;
END WHILE p2;
set res = 1 / res;
SELECT sum;
END IF;
IF y = 0 THEN
SET res = 1;
END IF;
SELECT res;
END;
&&
delimiter ;
-- 呼叫函式檢視結果
CALL method3();
三、資料庫的函式
1、基本函式
(1)常用方法
① 獲取字元的長度
char_length();
② 獲取字串的位元組數
length();
③ 擷取函式:
left("你好世界",1); -- 從左邊開始擷取多少個
right();從右邊擷取,同上
mid();從中間擷取
④ 時間函式
curdate(); -- 獲取當前日期:年月日
curtime(); -- 獲取當前時間
now(); -- 獲取當前的日期 + 時間
⑤ 去空格
ltrim(); -- 去掉前面空格
rtrim(); -- 去掉後面空格
trim(); -- 去掉前後空格
⑥ 數學函式
pow(); -- 指數運算,如select POW(2,3);
random(); -- 產生0-1的隨機小數
2、自定義函式
(1)自定義函式是可以實現一個特定功能的程式碼塊
(2)語法
① 建立函式
CREATE FUNCTION 函式名([引數名 資料型別]) RETURNS 返回值資料型別
BEGIN
函式的功能語句;
RETURN 返回值;
END;
注意:
- 函式體肯定會有返回值,但沒有也不會報錯,如果 RETURN 語句沒有放在函式體的最後,也不會報錯,但是不建議這麼放置;
- 如果函式體中只有一句話,可以省略 BEGIN 和 END;
- delimiter 語句可以用於設定結束標記。
② 查詢函式
-- 查詢函式
SHOW FUNCTION STATUS;
SHOW CREATE FUNCTION 函式名; -- 函式名後不加括號
③ 呼叫函式
SELECT 函式名(引數列表);
④ 刪除函式
DROP FUNCTION 函式名; -- 函式名後不加括號
Demo1:通過函式簡單計算
-- 計算1 + 2 方式1
delimiter &&
CREATE FUNCTION method() RETURNS INT
BEGIN
DECLARE sum INT DEFAULT 0;
DECLARE i INT DEFAULT 1;
DECLARE j INT DEFAULT 2;
SET sum := i + j;
RETURN sum;
END;
&&
delimiter ;
-- 呼叫函式檢視結果
SELECT method();
-- 計算1 + 2 方式2
delimiter &&
CREATE FUNCTION method(i INT,j INT) RETURNS INT
BEGIN
DECLARE sum INT DEFAULT 0;
SET sum := i + j;
RETURN sum;
END;
&&
delimiter ;
-- 呼叫函式檢視結果
SELECT method(1,2);
四、資料庫儲存過程 procedure
1、儲存過程概念
儲存過程類似於函式,是為了實現特定功能的程式碼,但是沒有返回值。
2、儲存過程的優點
(1)提高程式碼的重用性;
(2)簡化操作;
(3)減少了編譯次數並且減少了和資料庫伺服器的連線次數,提高了效率。
3、儲存過程語法
(1)建立儲存過程
CREATE PROCEDURE 儲存過程名(引數模式 引數名 引數型別)
BEGIN
儲存過程體(一組合法的SQL語句);
END
注意:
- 引數模式:
IN:表示該引數只能從儲存過程的外面傳到儲存過程的裡面使用;
OUT:表示該引數只能從儲存過程的裡面傳到儲存過程的外面使用;
INOUT:既可以從儲存過程的外面傳入到裡面使用,也可以從裡面傳入到外面使用。 - 如果儲存過程體僅僅只有一句話,BEGIN和END可以省略。
- 儲存過程體重的每條SQL語句的結尾必須要加分號";"。
- 儲存過程的結尾可以使用 DELIMITER 重新設定,語法:
delimiter 結束標記
如
delimiter &&
(2)查詢儲存過程
查詢儲存過程
SHOW PROCEDURE STATUS;
檢視儲存過程資訊
SHOW CREATE PROCDURE 儲存過程名;
(3)刪除儲存過程
DROP PROCEDURE 儲存過程名稱;
(4)呼叫儲存過程
CALL 儲存過程名(實參列表);
Demo1:儲存過程實現1 + 2的計算
-- 儲存過程實現1 + 2的計算
delimiter &&
CREATE PROCEDURE demo1()
BEGIN
DECLARE i INT DEFAULT 1;
DECLARE j INT DEFAULT 2;
DECLARE sum INT DEFAULT 0;
SET sum := i + j;
SELECT sum;
END
&&
delimiter ;
-- 呼叫函式檢視結果
CALL demo1();
Demo2:儲存過程實現100-500之間的累加
-- 儲存過程實現100-500之間的累加
delimiter &&
CREATE PROCEDURE demo2()
BEGIN
DECLARE sum INT DEFAULT 0;
DECLARE i INT DEFAULT 100;
WHILE i <= 500 DO
SET sum := sum + i;
SET i := i + 1;
END WHILE;
SELECT sum;
END
&&
delimiter ;
-- 呼叫函式檢視結果
CALL demo2();
Demo3:使用儲存過程向資料庫表中插入資料
-- 使用儲存過程向資料庫表中插入資料
delimiter &&
CREATE PROCEDURE demo3()
BEGIN
DECLARE i int DEFAULT 7;
p1:WHILE i <= 100 DO
INSERT INTO student1 VALUES(i,'張三',"s007","id7");
SET i = i + 1;
END WHILE p1;
SELECT * FROM student1;
END;
&&
delimiter ;
CALL demo3();
Demo4:IN、OUT、INOUT的分析
Demo5:建立儲存過程實現傳入一個日期,格式化成yyyy年mm月dd日並返回
-- 建立儲存過程實現傳入一個日期,格式化成yyyy年mm月dd日並返回
delimiter &&
CREATE PROCEDURE datedemo(IN mydate DATETIME,OUT strDate VARCHAR(50))
BEGIN
SELECT DATE_FORMAT(mydate,'%y年%m月%d日') INTO strDate;
END;
&&
delimiter ;
CALL datedemo(NOW(),@str);
SELECT @str;
五、資料庫觸發器 trigger
1、觸發器概念
不用主動呼叫,一旦滿足一定條件,會自動觸發。
2、觸發器語法
(1)建立觸發器
create trigger 觸發器名稱 觸發時機 觸發事件 on 表名 for each row
begin
觸發器的程式碼;
end
Demo:建立一個觸發器
-- 建立一個觸發器
CREATE TRIGGER tr AFTER INSERT ON orders FOR EACH ROW
BEGIN
UPDATE product SET pnum = pnum - new.onum WHERE pid = old.pid;
END
(2)查詢觸發器
SHOW TRIGGERS;
(3)刪除觸發器
DROP TRIGGER 觸發器名字;
3、觸發器時機、事件
(1)觸發器時機:after,before
(2)觸發器事件:insert,delete,update
(3)new:如果是新增語句,使用new。
(4)old:如果是修改和刪除語句,使用old。