1. 程式人生 > 其它 >MySQL基礎筆記(6) - 遊標&觸發器&事務

MySQL基礎筆記(6) - 遊標&觸發器&事務

本文為MySQL基礎入門相關筆記,同時參考了尚矽谷的BV1xW411u7ax網課和《MySQL必知必會》兩者,主要用於個人記錄與分享,如有錯誤歡迎留言指出

遊標&觸發器&事務

目錄

1. 遊標

定義:有時需要在檢索出來的行中前進或後退一行/多行,這就是使用遊標的原因。遊標是一個被儲存在Mysql伺服器上的資料庫查詢,它是被該語句檢索出來的結果集。在儲存了遊標之後,應用程式可以根據需要滾動或遊覽其中的資料。Mysql的遊標只能用於儲存過程和函式

注意:建立語句均只能在命令列視窗執行,請先在命令列登入並轉到當前庫,然後再貼上進行操作

#1.建立遊標
DELIMITER //
CREATE PROCEDURE processorders()
BEGIN
    DECLARE ordernumbers CURSOR
    FOR
    SELECT order_num FROM orders;
END//

#2.開關遊標
OPEN ordernumbers;
CLOSE ordernumbers;

#例項
DELIMITER //
CREATE PROCEDURE processorders()
BEGIN
	-- 定義三個變數
    DECLARE done BOOLEAN DEFAULT 0;
    DECLARE o INT;
    DECLARE t DECIMAL(8,2);
    
    
    DECLARE ordernumbers CURSOR
    FOR
    SELECT order_num FROM orders;
    -- 當沒有更多的行供repeat迴圈的時候,將done設定為1,停止迴圈
    DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET done=1;
    
    -- 建立ordertotals表
    CREATE TABLE IF NOT EXISTS ordertotals
    (order_num INT,total DECIMAL(8,2));
    
    OPEN ordernumbers;
    
    -- 迴圈直到done不為0時停止
    REPEAT
    	-- 遊標結合repeat查看錶每一行並存入到變數o中
		FETCH ordernumbers INTO o;
		-- ordertotal是上一章中用來統計商品總價格的儲存流程s
		CALL ordertotal(o,1,t);
		-- 將計算結果插入到新表ordertotals中
		INSERT INTO ordertotals(order_num,total)
		VALUES(o,t);
    UNTIL done END REPEAT;
    
    CLOSE ordernumbers;
END//

SELECT *
FROM ordertotals;
#本例項跨度較大,重在理解

2. 觸發器

定義:觸發器是Mysql響應DELETE,INSERT,UPDATE語句而自動執行的一條/一組Mysql語句

2.1 觸發器的建立與刪除

  • 建立觸發器

    語法:create trigger [觸發器名] [觸發時機] [觸發器響應的活動] ON [觸發器關聯的表]

    CREATE TRIGGER newproduct AFTER INSERT ON products
    FOR EACH ROW SELECT 'Product added' INTO @asd;
    
    #只有表才能支援觸發器,檢視不支援
    #觸發器按每個表每個事件每次地定義,每個表每個事件每次只允許擁有一個觸發器。因此,每個表最多支援6個觸發器(每條insert,update,delete前後)。單一觸發器不能與多個事件或多個表關聯
    #Mysql 5之後不允許觸發器直接返回值,這裡將返回值儲存到了變數asd中
    
  • 刪除觸發器

    DROP TRIGGER newproduct;
    

2.2 觸發器的使用

  • INSERT觸發器

    • INSERT觸發器程式碼內,可以引用一個名為NEW的虛擬表,可以由此訪問那些被插入的行
    • 在BEFORE INSERT觸發器中,NEW中的值也可以被更新(允許更改被插入的值)
    • 對於AUTO_INCREMENT列,NEW在INSERT執行前包含0,在執行後包含新的自動生成的值
    #例項
    #設定一個觸發器,每當插入完成後,從new表中獲得order_num的新數值,然後儲存到asd中
    CREATE TRIGGER neworder AFTER INSERT ON orders
    FOR EACH ROW SELECT new.order_num INTO @asd;
    
    INSERT INTO orders(order_date,cust_id)
    VALUES(NOW(),10001);
    
    SELECT @asd;
    
  • DELETE觸發器

    • DELETE觸發器程式碼內,可以引用一個名為OLD的虛擬表,訪問被刪除行

    • OLD的中的值全部都是隻讀的,不可更改

    #例項
    #設定一個觸發器,在刪除行前,將行的資料轉移到另一個臨時表中
    CREATE TRIGGER deleteorder BEFORE DELETE ON orders
    FOR EACH ROW
    BEGIN
    	INSERT INTO archive_orders(order_num,order_date,cust_id)
    	VALUES(OLD.order_num,OLD.order_date,OLD.cust_id);
    END;
    
  • UPDATE觸發器

    • UPDATE觸發器程式碼總,可以引用OLD的虛擬表訪問UPDATE之前的值,引用NEW的虛擬表訪問UPDATE後的值
    • 在BEFORE UPDATE觸發器中,NEW中的值可能也被更新
    • OLD中的值全都是隻讀的,不能更新
    #例項
    #設定一個觸發器,保證州名的縮寫總是大寫
    CREATE TRIGGER updatevender BEFORE UPDATE ON vendors
    FOR EACH ROW SET NEW.vend_state = Upper(NEW,vend_state);
    

3. 事務

3.1 事務的使用

定義:事務是指一個或一組sql語句組成一個執行單元,這個執行單元要麼全部執行,要麼全部不執行。一個事務一旦執行失敗,就會回滾到上一個步驟。(MyISAM引擎不支援事務處理,一般使用InnoDB引擎)

特性(ACID):

  • 原子性:一個事務不可再分割,要麼都執行要麼都不執行
  • 一致性:一個事務執行會使資料從一個一致狀態切換到另一個一致狀態
  • 隔離性:一個事物的執行不受其它事務的干擾
  • 永續性:一個事務一旦提交,則會永久的改變資料庫的資料

事務的分類:

  • 隱式事務:事務沒有明顯的開啟和結束的標記(比如insert,update,delete語句)
  • 顯式事務:事務具有明顯的開啟和結束的標記(使用前必須設定自動提交功能為禁用)
#1.開啟事務
SET autocommit=0;
START TRANSACTION;
#2.編寫一組事務的語句
UPDATE account SET balance = 500;
UPDATE account SET balance = 1500;
#3.結束事務
COMMIT; #提交事務
#OR
ROLLBACK; #回滾

#4.savepoint的使用:savepoint一般搭配rollback使用,用於指定回滾的位置
SET autocommit=0;
START TRANSACTION;
DELETE FROM account WHERE id=25;
SAVEPOINT a; #設定儲存點
DELETE FROM account WHERE id=28;
ROLLBACK TO a; #回滾到儲存點

#在事務中,回滾可以對INSERT,UPDATE,DELETE生效,但是對CREATE,DROP,TRANSACTION無效

3.2 事務的隔離級別

事務的隔離級別/併發問題 髒讀 不可重複讀 幻讀
read uncommitted
read committed ×
repeatable read × ×
serializable × × ×

檢視隔離級別:select @@tx_isolation;

設定隔離級別:set session|global transaction isolation level 隔離級別;