MySQL-事務&儲存過程&觸發器-黃海鋒
一、事務
原子性:一個事務(transaction)中的所有操作,要麼全部完成,要麼全部不完成,不會結束在中間某個環節。事務在執行過程中發生錯誤,會被回滾(Rollback)到事務開始前的狀態,就像這個事務從來沒有執行過一樣。
一致性:在事務開始之前和事務結束以後,資料庫的完整性沒有被破壞。這表示寫入的資料必須完全符合所有的預設規則,這包含資料的精確度、串聯性以及後續資料庫可以自發性地完成預定的工作。
隔離性:資料庫允許多個併發事務同時對其資料進行讀寫和修改的能力,隔離性可以防止多個事務併發執行時由於交叉執行而導致資料的不一致。事務隔離分為不同級別,包括讀未提交(Read uncommitted)、讀提交(read committed)、可重複讀(repeatable read)和序列化(Serializable)。
永續性:事務處理結束後,對資料的修改就是永久的,即便系統故障也不會丟失。
1.事務控制語句
BEGIN 或 START TRANSACTION 顯式地開啟一個事務;
COMMIT 也可以使用 COMMIT WORK,不過二者是等價的。COMMIT 會提交事務,並使已對資料庫進行的所有修改成為永久性的;
ROLLBACK 也可以使用 ROLLBACK WORK,不過二者是等價的。回滾會結束使用者的事務,並撤銷正在進行的所有未提交的修改;
SAVEPOINT identifier,SAVEPOINT 允許在事務中建立一個儲存點,一個事務中可以有多個 SAVEPOINT;
RELEASE SAVEPOINT identifier 刪除一個事務的儲存點,當沒有指定的儲存點時,執行該語句會丟擲一個異常;
ROLLBACK TO identifier 把事務回滾到標記點;
SET TRANSACTION 用來設定事務的隔離級別。InnoDB 儲存引擎提供事務的隔離級別有READ UNCOMMITTED、READ COMMITTED、REPEATABLE READ 和 SERIALIZABLE。
2.MYSQL 事務處理主要有兩種方法:
1、用 BEGIN, ROLLBACK, COMMIT來實現
BEGIN 開始一個事務
ROLLBACK 事務回滾
COMMIT 事務確認
2、直接用 SET 來改變 MySQL 的自動提交模式:
SET AUTOCOMMIT=0 禁止自動提交
SET AUTOCOMMIT=1 開啟自動提交
3.提交事務
1 CREATE TABLE runoob_transaction_test( id int(5)) engine=innodb; # 建立資料表 2 3 select * from runoob_transaction_test; 4 5 begin; # 開始事務 6 7 insert into runoob_transaction_test value(5); 8 9 insert into runoob_transaction_test value(6); 10 11 commit; # 提交事務 12 13 select * from runoob_transaction_test;
4.回滾事務
1 begin; # 開始事務 2 3 insert into runoob_transaction_test values(7); 4 5 rollback; # 回滾 6 7 select * from runoob_transaction_test; # 因為回滾所以資料沒有插入
二、儲存過程
MySQL 5.0 版本開始支援儲存過程。 儲存過程(Stored Procedure)是一種在資料庫中儲存複雜程式,以便外部程式呼叫的一種資料庫物件。
儲存過程是為了完成特定功能的SQL語句集,經編譯建立並儲存在資料庫中,使用者可通過指定儲存過程的名字並給定引數(需要時)來呼叫執行。
儲存過程思想上很簡單,就是資料庫 SQL 語言層面的程式碼封裝與重用。
優點:
儲存過程可封裝,並隱藏複雜的商業邏輯。
儲存過程可以回傳值,並可以接受引數。
儲存過程無法使用 SELECT 指令來執行,因為它是子程式,與檢視 表,資料表或使用者定義函式不同。
儲存過程可以用在資料檢驗,強制實行商業邏輯等。
1 CREATE DATABASE IF NOT EXISTS web_student DEFAULT CHARSET utf8; 2 USE web_student; 3 #學生表 4 CREATE TABLE student( 5 NAME VARCHAR(20), 6 PASSWORD VARCHAR(20), 7 sid INT PRIMARY KEY AUTO_INCREMENT, 8 birthday DATE 9 ); 10 INSERT INTO student(NAME,PASSWORD,birthday)VALUES 11 ('張三','123456','2000-01-01'), 12 ('李四','123456','2000-01-02'), 13 ('王五','123456','2000-01-03'), 14 ('老六','123456','2000-01-04'), 15 ('趙七','123456','2000-01-05'), 16 ('老八','123456','2000-01-06'); 17 18 SELECT * FROM student; 19 20 #成績表 21 CREATE TABLE cj( 22 num INT, 23 stu_id INT, 24 stu_name VARCHAR(20), 25 math FLOAT, 26 chinese FLOAT, 27 english FLOAT 28 ); 29 30 31 #建立儲存過程 32 DELIMITER $ 33 CREATE PROCEDURE test() 34 BEGIN 35 SELECT * FROM student; 36 SELECT * FROM cj; 37 END $ 38 DELIMITER; 39 #呼叫儲存過程 40 CALL test(); 41 42 43 44 #建立儲存過程 45 DELIMITER $ 46 CREATE PROCEDURE test2() 47 BEGIN 48 #宣告變數型別 49 DECLARE un VARCHAR(50) DEFAULT ''; 50 #給username變數賦值 51 SET un = 'hhhhhh'; 52 #將查詢結果賦值給username變數 53 SELECT NAME INTO un FROM student WHERE sid=1; 54 #查詢username變數,放回 55 SELECT un; 56 END $ 57 DELIMITER ; 58 59 CALL test2(); 60 61 62 63 64 #建立儲存過程 65 DELIMITER $ 66 CREATE PROCEDURE test3() 67 BEGIN 68 BEGIN 69 #宣告變數型別 70 DECLARE un VARCHAR(50) DEFAULT ''; 71 #給username變數賦值 72 SET un = 'hhhhhh'; 73 #將查詢結果賦值給username變數 74 SELECT NAME INTO un FROM student WHERE sid=1; 75 #查詢username變數,放回 76 SELECT un; 77 END; 78 BEGIN 79 #宣告變數型別 80 DECLARE un VARCHAR(50) DEFAULT ''; 81 #給username變數賦值 82 SET un = 'hhhhhh'; 83 #將查詢結果賦值給username變數 84 SELECT NAME INTO un FROM student WHERE sid=2; 85 #查詢username變數,放回 86 SELECT un; 87 END; 88 END $ 89 DELIMITER ; 90 91 CALL test3();
三、觸發器
觸發器概念:觸發器(trigger):監視某種情況,並觸發某種操作,它是提供給程式設計師和資料分析員來保證資料完整性的一種方法,它是與表事件相關的特殊的儲存過程,它的執行不是由程式呼叫,也不是手工啟動,而是由事件來觸發,例如當對一個表進行操作( insert,delete, update)時就會啟用它執行。
觸發器經常用於加強資料的完整性約束和業務規則等。 觸發器建立語法四要素:
1.監視地點(table)
2.監視事件(insert/update/delete)
3.觸發時間(after/before)
4.觸發事件(insert/update/delete)
觸發器SQL語法:
1 create trigger triggerName 2 after/before insert/update/delete on 表名 3 for each row #這句話在mysql是固定的 4 begin 5 sql語句; 6 end;
1 CREATE DATABASE IF NOT EXISTS web_student DEFAULT CHARSET utf8; 2 USE web_student; 3 #學生表 4 CREATE TABLE student( 5 NAME VARCHAR(20), 6 PASSWORD VARCHAR(20), 7 sid INT PRIMARY KEY AUTO_INCREMENT, 8 birthday DATE 9 ); 10 INSERT INTO student(NAME,PASSWORD,birthday)VALUES 11 ('張三','123456','2000-01-01'), 12 ('李四','123456','2000-01-02'), 13 ('王五','123456','2000-01-03'), 14 ('老六','123456','2000-01-04'), 15 ('趙七','123456','2000-01-05'), 16 ('老八','123456','2000-01-06'); 17 18 SELECT * FROM student; 19 20 #成績表 21 CREATE TABLE cj( 22 num INT, 23 stu_id INT, 24 stu_name VARCHAR(20), 25 math FLOAT, 26 chinese FLOAT, 27 english FLOAT 28 ); 29 30 SELECT * FROM cj; 31 #觸發器 32 #建立觸發器 33 CREATE TRIGGER ins_stu 34 #在什麼之後,在這個表插入 35 AFTER INSERT ON student FOR EACH ROW 36 #begin 37 INSERT INTO cj VALUES(1,new.sid,new.name,90.5,85.5,75.0); 38 #end; 39 40 #執行觸發器 41 INSERT INTO student(NAME,PASSWORD,birthday)VALUES 42 ('苦九','123456','2000-01-07');