1. 程式人生 > 資料庫 >MySQL 資料庫(六)—— 資料庫程式設計:資料庫的變數、資料庫控制語句、資料庫函式、儲存過程、觸發器等

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。