1. 程式人生 > 其它 >從0到1學資料庫:資料操作與事務控制

從0到1學資料庫:資料操作與事務控制

技術標籤:0-1資料庫

點選上方“羅曉勝”,馬上關注,您的支援對我幫助很大

上期文章

/ 前言 /

查詢我們已經很熟悉,接下我們試試CRUD其他的,增加幾條資料,修改一些資料,和刪除一些資料,還有事務進行控制。

/ 正文 /

要點

• INSERT語句
• UPDATE語句
• DELETE語句
• COMMIT命令
• ROLLBACK命令
• 管理鎖

資料操作與事務控制

• 資料操作語言(DML:Data Manipulation Language) • 主要包括以下語句:– INSERT – UPDATE – DELETE – MERGE

• 事務是一組相關的DML語句的邏輯組合。事務控制主要包括下 列命令:– COMMIT – ROLLBACK – SAVEPOINT

插入資料INSERT語法結構

• 語法如下:

INSERT INTO 表名[(列名1[,列名2,…,列名n])] VALUES (值1[,值2,…,值n]);

– 一次只插入一行 – NULL的使用,連續的單引號('')也可以表示空值。– 插入日期型資料 – 插入特殊字元 – 插入多行資料 – 按列的預設順序列出各個列的值 – 在Insert子句中可以隨意列出列名和他們的值 – 字元和日期型資料應該包含在單引號中

INSERT語句插入空值(NULL)

• 例 新增一條使用者資料

INSERT INTO student VALUES(null,'阿拉善',23,3,88,'2020-01-01');

• 這裡ID是自增,所以我們用null代替(有設定預設值的也是用null代替,系統會自動用預設值初始化)

– 符合SQL:1999標準 – 可以使用顯示預設值控制預設值的使用 – 顯示預設值可以在insert和update語句中使用

• 例 新增使用者資料(班級未知or分數未知)

INSERT INTO student VALUES(null,'阿拉善',23,null,88,'2020-01-01');
INSERT INTO student VALUES(null,'阿拉善',23,3,null,'2020-01-01');

INSERT語句插入日期型資料

• 例 可選擇年月日或者完整年月日時分秒插入資料,(時間通用格式 yyyy-MM-dd hh:mm:ss)

INSERT INTO student VALUES(null,'阿拉善',23,3,88,'2020-01-01');
INSERT INTO student VALUES(null,'阿拉善',23,3,88,'2020-01-01 01:01:01');
INSERT INTO student VALUES(null,'阿拉善',23,3,88,str_to_date('08/09/2008', '%m/%d/%Y'));
INSERT INTO student VALUES(null,'阿拉善',23,3,88,str_to_date('08.09.2008 08:09:30', '%m.%d.%Y %h:%i:%s'));

INSERT語句插入特殊字元

使用“\”符對特殊符號轉義 ""替換為"\" "'"替換為"''"

以下SQL插入資料會報錯
INSERT INTO student VALUES(null,''阿拉善'',23,3,88,'2020-01-01');
INSERT INTO student VALUES(null,'\阿拉善\',23,3,88,'2020-01-01');

轉義字元
INSERT INTO student VALUES(null,'\'阿拉善\'',23,3,88,'2020-01-01');
INSERT INTO student VALUES(null,'''阿拉善''',23,3,88,'2020-01-01');
INSERT INTO student VALUES(null,'\\阿拉善\\',23,3,88,'2020-01-01');

INSERT語句插入多行資料

• 語法

INSERT INTO表名[(列名1[,列名2,…,列名n])] 子查詢 ;

• 例 將建立時間大於“2000-01-01”使用者資訊複製到 student表中。

INSERT INTO student SELECT * FROM student WHERE c_create_date<('2000-01-01');

不必書寫values子句 INSERT子句中列的數量和型別必須和子查詢中列的數量 和型別相匹配

修改資料UPDATE語法結構

• UPDATE語法結構

UPDATE 表名 SET 列名=表示式[,列名=表示式, [WHERE 條件表示式];]

• UPDATE簡單修改

UPDATE student SET c_score=c_score+1 where id = 1;

• 嵌入子查詢修改

UPDATE student SET c_score=c_score+(SELECT AVG(c_score) FROM student) WHERE where id = 1;

根據查詢結果批量更新

將三班和一班同名的使用者批量更新分數和年齡

UPDATE student t1,(select * from student where c_class = 3) t2
SET t1.c_score = t2.c_score,t1.age = t2.age 
where t1.name = t2.name and (t1.c_class = 1)

注:還可以對t2新增分組控制查詢條數(保證t2在某一緯度只有一條資料)

修改資料(完整性錯誤)

• update student set id = 55 where id = 1;

• ORA-02291: 違反完整約束條件 (NEU.EMP_DEPT_FK) - 未找 到父項關鍵字

刪除資料DELETE語法結構

• DELETE語法結構 DELETE [FROM] 表名 [WHERE 條件表示式];

• DELETE刪除資料 DELETE FROM student WHERE id=10;

• 例 刪除所有名為"三班"的使用者 DELETE FROM student WHERE c_class IN (SELECT id FROM t_class WHERE name ='三班') ;

• DELETE語句不能刪除被其他表引用了的記錄值,也即外來鍵。

Merge儲存引擎

現在有這麼一個問題,怎樣樣統計所有的分表(假設按天分表)資料,所有的分表資料結構、型別相同。我們肯定能想到以下兩種方案:第一種是最笨的方法,就是迴圈查詢所有表資料(肯定不能採用);第二種方法是,利用中介軟體,redis或者mycat,然後定時輪詢,這樣開銷也很大。

mysql有很多引擎,如engine=innodb和engine=myisam,其實還有Merge儲存引擎,可直接對多張表合併

假設有user_1、user_2、user_3三張表
CREATE TABLE `user_1` (
`id` int(11) NOT NULL AUTO_INCREMENT ,
`user_name` varchar(255) NULL ,
`user_sex` varchar(255) NULL ,
`user_birth_date` datetime NULL ,
PRIMARY KEY (`id`)
)ENGINE = MYISAM DEFAULT CHARSET=utf8mb4;
。。。
user_2、user_3

建立user_merge表
CREATE TABLE `user_merge` (
`id` int(11) NOT NULL AUTO_INCREMENT ,
`user_name` varchar(255) NULL ,
`user_sex` varchar(255) NULL ,
`user_birth_date` datetime NULL ,
PRIMARY KEY (`id`)
)ENGINE = MERGE UNION = (user_1,user_2,user_3);

然後select 查詢user_merge即可
select * from user_merge

事務概率

• 概念:事務(Transaction)也稱工作單元,是一個或多個SQL 語句所組成的序列,這些SQL操作作為一個完整的工作單元, 要麼全部執行,要麼全部不執行。通過事務的使用,能夠使一 系列相關操作關聯起來,防止出現數據不一致現象。

• 事務的組成:在ORACLE資料庫中,事務由以下語句組成:

– 一組相關的DML語句,修改的資料在該組語句中保持一致

– 一個 DDL語句或者一個 DCL語句或者一個TCL語句

事務特徵

• 可用四個字母的縮寫表示:即ACID

• 原子性(Atomicity) – 事務就像一個獨立的工作單元。原子性保證要麼所有的操 作都成功,要不全都失敗。如果所有的動作都成功了,我 們就說這個事務成功了,不然就是失敗的,然後回滾。

• 一致性(Consistency) – 一旦事務完成了(不管是成功的,還是失敗的),整個系 統處於操作規則的統一狀態,也就是說,資料不會損壞。

• 隔離性(Isolation) – 事務的隔離性是指資料庫中一個事務的執行不能被其它事 務干擾。所以,事務應該隔離起來,目的為了防止同時的 讀和寫操作。這就需要事務與鎖同時使用。

• 永續性(Durability) – 事務的永續性也稱為永久性(Permanence),指事務一旦 提交,則其對資料庫中資料的改變就是永久的。

事務控制

• 事務的控制分為:顯式控制及隱式控制。

• 顯式控制:– 顯式提交:Commit – 顯式回滾:Rollback

• 隱式控制:– 隱式提交:當下列任意一種情況發生時,會發生隱式提交 a. 執行一個DDL 語句 b. 執行一個DCL 語句

– 隱式回滾:當下列任意一種情況發生時,會發生隱式回滾 a. 客戶端連線到伺服器端異常中斷 b. 系統崩潰

事務的主要命令

• 事務控制的命令主要有以下三個:

– 事務提交:COMMIT – 事務回滾:ROLLBACK – 設立儲存點:SAVEPOINT(作為輔助命令使用)

• 設定儲存點語法:– SAVEPOINT 儲存點名稱;——定義儲存點 – ROLLBACK TO儲存點名稱; ——回滾到已定義儲存點

事務的開始和結束

• 開始:事務開始於上一個事務結束後執行的第一個DML語句 • 結束:事務結束於下面的任一種情況的發生:

– 執行了COMMIT 或者ROLLBACK命令 – 隱式提交(單個的DDL或DCL語句)或自動提交 – 使用者退出 – 系統崩潰

事務自動提交

背景知識:mysql事務支援的引擎是InnoDB 預設情況下autocommit的值為1

當autocommit為開啟狀態時,即使沒有手動start transaction開啟事務,mysql預設也會將使用者的操作當做事務即時提交

• 設定格式:

SET AUTOCOMMIT [ON|OFF];

事務控制示例

DELETE FROM test ; ROLLBACK; ——撤消DELETE操作 INSERT INTO test VALUES(’A’); SAVEPOINT insert_a; ——定義insert_a儲存點 INSERT INTO test VALUES(’B’); SAVEPOINT insert_b; ——定義insert_b儲存點 INSERT INTO test VALUES(’C’); ROLLBACK TO insert_b; ——撤消操作到insert_b儲存點 DELETE FROM test WHERE test_str = ‘A’; COMMIT; ——將所有修改寫入資料庫 ROLLBACK; ——所有操作已經COMMIT提交,不能 回滾

事務執行Commit或Rollback前的資料狀態

– 資料變化前的狀態可以被恢復 – 當前會話可以使用SELECT語句來驗證 DML操作後的結果 – 其它會話不能檢視由當前使用者的DML操作結果 – 受影響記錄被鎖定,也就是其它使用者不能改變受影響記錄 中的資料

• Commit後的狀態 – 在資料庫中資料變化成為永久性的 – 先前的資料狀態永久性的消失 – 所有使用者/會話都可以查詢提交後的結果 – 鎖定的記錄被釋放,可以有效地被其他使用者操作 – 所有的儲存節點被清除

• Rollback後的資料狀態 – 使用ROLLBACK 可以放棄所有懸而未決的變化。¯資料變化是可以撤銷的 ¯先前的資料狀態被恢復 ¯鎖定的記錄被釋放 ¯所有的儲存節點被清除

事務的讀一致性

• 讀一致性保證了不同會話在同一時間檢視資料時,資料一致。

• 在兩個不同級別上提供讀一致性:語句級讀一致性和 事務級一致性。

• 事務級一致性,當一個會話正在修改資料時,其它的會話將看 不到該會話未提交的修改。

• 語句級讀一致性,保證單個查詢所返回的資料與該查詢開始時 刻相一致。所以一個查詢從不會看到在查詢執行過程中提交的 其它事務所作的任何修改。

鎖-併發事務

• 併發事務

– 併發事務:如果多個事務同時訪問某一個資源,比如同時 修改表中的某一行。

併發事務常見問題

– 併發事務可能出現如下問題:

• 1.髒讀取:就是讀取了未提交的資料,如B事務讀取了A 事務未提交的資料 • 2.不可重複讀取:就是一個事務在讀取一個數據時,資料 不同,可能是另一個事務修改了資料。• 3.更新丟失:就是兩個事務同時更新了一條資料,先更新 的就會丟失資料。• 4.幻想讀:事務A在讀取資料的時候,資料發生了變化。

鎖的概念

• 鎖用來在多使用者併發訪問和操作資料庫時保證資料的一致性。鎖由系統自動管理。如一個DML操作,預設的機制 是在DML操作涉及到的行上加鎖(行級別),但不會在更高的 級別(表級別)上加更嚴格的鎖,比如只改某行的資料不會鎖 住整個表。這提供了很好的併發性,因為整個表沒有鎖定,只 是某些行被鎖定了,其他使用者可以修改其他行資料。• 查詢不需要任何鎖。• 鎖的生命週期,鎖在被相關的操作申請並持有後,會一直保持 到事務的結束。事務結束後,鎖才會被釋放。• 鎖的內部維護機制是採用排隊機制(enqueue),一個物件的 排它鎖被持有後,該物件相同級別的鎖被其他事務申請時候, 所有等待該鎖的事務都在一個等待佇列中排隊,其他事務處於 等待狀態。直到該鎖被釋放,等待的事務才重新競爭使用該資 源。

• 鎖的模式 – 排它鎖模式(Exclusive)排它鎖在被釋放之前,會阻止其 鎖住的資源被其他任何事務共享。– 共享模式(Share)

鎖的分類

• 兩種型別的鎖,DML鎖和DDL鎖。• DML鎖,也稱資料鎖,用於在資料被多個不同的使用者改變時, 保證資料的完整性。• DDL鎖,也稱為資料字典鎖,執行DDL語句時,DDL語句涉及 到的物件獲得DDL鎖。由於被持有的時間很短,因此很少看到 衝突的DDL鎖,並且以nowait方式被請求。

3種DDL鎖型別:

– 排它的DDL鎖,很多物件的建立、修改和刪除定義時候都 需要獲得該鎖。比如執行Create Table、Drop Table等時會 獲得表上的排它DDL鎖。– 共享的DDL鎖。在執行Grant、Create Procedure等命令時, 會獲得命令相關操作物件的共享DDL鎖。– Breakable Parse Lock,用來在共享SQL區校驗語句。

鎖的使用

• 實現加鎖機制主要有兩種方式:– 1.自動加鎖 – 2.手動加鎖

• 自動加鎖 – 使用者在執行INSERT,UPDATE,DELETE,DCL, DDL語句時,ORACLE會自動加鎖。– 在一個事務中,ORACLE會自動鎖定執行以上語句的 資料庫物件,只有事務結束(提交或者回滾),資源 才能被釋放。– 預設情況下,更新資料時ORACLE會自動提供排他鎖, 使不同使用者在更新表中同一資料時不會發生衝突。l 例 模擬兩個會話,同時修改員工編號198的員工資訊

• 手動加鎖 – 除了自動加鎖之外,也可以使用手動加鎖。– 語法常見的有兩種:• 1.表加鎖語法 LOCK TABLE 表名 IN 鎖型別 MODE [NOWAIT] 鎖型別: Exclusive,Share • 2.行加鎖語法 SELECT…FROM…FOR UPDATE [NOWAIT] NOWAIT選項是當申請加鎖不成功時,就不再等待

使用鎖的常見問題

• 如使用鎖的方式不當,可能會產生鎖衝突,不適當的使用方式 包括:– 不必要的高級別的鎖 – 長時間執行的事務 – 沒有提交的事務 – 其他產品產生了高級別的鎖

• 死鎖:當兩個或者兩個以上的使用者彼此等待被對方鎖定的資源 時,就有可能產生死鎖。

鎖的例子(死鎖)

• 會話A在時間T1修改資源X,未進行提交 • 會話B在時間T2修改資源Y,未進行提交 • 會話A在時間T3修改資源Y,未進行提交 • 會話B在時間T4修改資源X,死鎖產生

/ 總結 /

本文主要講了增加、修改、刪除資料這些操作,作為一個合格的程式設計師,CRUD的熟練是基礎標準

往期推薦:

如何入門做軟體開發

為什麼我不推薦入行程式設計師

做全棧開發很難嗎

關注我的公眾號,學習技術或投稿

圖片

長按上圖,識別圖中二維碼即可關注