4 資料更新
4 資料更新
4-1 資料的插入(INSERT語句的使用方法)
通過create table語句創建出來的表,可以將其比作一個空空如也的箱子。只有把資料裝入到這個箱子後,它才能稱為資料庫。用來裝入資料的SQL就是INSERT(插入)。
什麼是INSERT |
CREATE TABLE shohinIns ( shohin_id CHAR(4) NOT null, shohin_mei VARCHAR(100) NOT NULL, shohin_bunrui VARCHAR(32) NOT NULL, hanbai_tanka INTEGER DEFAULT 0, shiire_tanka INTEGER, totokubi DATE, PRIMARY KEY (shohin_id) ); |
INSERT語句的基本語法 |
-- INSERT INTO <表名> (列1,列2, 列3, 。。。) VALUES (值1,值2,值3,。。。); 包括:列清單和值清單(兩者數量必須保持一致)
INSERT INTO shohinIns (shohin_id, shohin_mei, shohin_bunrui, hanbai_tanka, shiire_tanka, totokubi) VALUES ('0001', 'T恤衫', '衣服', 1000, 500, '2009-09-20'); |
列名和值用逗號隔開,分別括在()內,這種形式稱為清單。
法則4-1 |
原則上,執行一次INSERT語句會插入一行資料。(其實很多RDBMS都支援一次INSERT多行資料,這樣的功能稱為“多行INSERT(multi row INSERT)”,一般不建議使用)。 |
對錶進行全列INSERT時,可以省略表名後的列清單。這時VALUES子句的值會預設按照從左到右的順序賦給每一列。
列清單的省略 |
INSERT INTO shohinIns VALUES ('0005', '高壓鍋', '廚房用具', 6800, 5000, '2009-01-15'); |
INSERT語句中想給某一列賦予NULL值時,可以直接在VALUES子句的值清單中寫入NULL。
但是,想要插入NULL的列一定不能設定NOT NULL約束。向設定了NOT NULL約束的列中插入NULL時,INSERT語句會出錯,資料插入失敗。
插入失敗指的是希望通過INSERT語句插入的資料無法正常插入到表中,但之前已經插入的資料並不會被破壞。
插入NULL |
INSERT INTO shohinIns (shohin_id, shohin_mei, shohin_bunrui, hanbai_tanka, shiire_tanka, totokubi) VALUES ('0006', '叉子', '廚房用具', 500, NULL, '2009-09-20'); |
通過顯式方法插入預設值(初始值),預設值的設定,可以通過在建立表的CREATE TABLE語句中設定DEFAULT約束來實現。
在VALUES子句中指定DEFAULT關鍵字(顯示方式插入預設值);
通過隱式方式插入預設值,插入預設值時也可以不使用DEFUALUT關鍵字(隱式方式插入預設值,即值什麼都不寫);
那麼,在實際使用中哪種方法更好呢?筆者建議大家使用顯示的方法。
說的省略列名,還有一定要說明以下。如果省略了沒有設定預設值的列的話,該列的值就會被設定為NULL。因此,如果省略的是設定了NOT NULL約束的列的話,INSERT語句就會出錯。
插入預設值 |
INSERT INTO shohinIns (shohin_id, shohin_mei, shohin_bunrui, hanbai_tanka, shiire_tanka, totokubi) VALUES ('0007', '擦菜飯', '廚房用具', DEFAULT, 790, '2009-04-28');
SELECT * FROM shohinIns WHERE shohin_id = '0007';
INSERT INTO shohinIns (shohin_id, shohin_mei, shohin_bunrui, hanbai_tanka, totokubi) VALUES ('0008', '圓珠筆', '辦公用品', 100, '2009-11-11');
INSERT INTO shohinIns (shohin_id, shohin_bunrui, hanbai_tanka, shiire_tanka, totokubi) VALUES ('0009', '辦公用品', 1000, 500, '2009-12-12'); |
法則4-2 |
省略INSERT語句中的列名,就會自動設定為該列的預設值(沒有預設值時會設定為NULL)。 |
插入資料的方法,除了使用VALUSE子句指定具體的資料之外,還可以從其他表中複製資料。
從其他表中複製資料 |
-- 用來插入資料的商品複製表 CREATE TABLE shohinCopy ( shohin_id CHAR(4) NOT null, shohin_mei VARCHAR(100) NOT NULL, shohin_bunrui VARCHAR(32) NOT NULL, hanbai_tanka INTEGER, shiire_tanka INTEGER, torokubi DATE, PRIMARY KEY (shohin_id) );
-- 將商品表中的資料複製到商品複製表中 INSERT INTO shohinCopy (shohin_id, shohin_mei, shohin_bunrui, hanbai_tanka, shiire_tanka, torokubi) SELECT shohin_id, shohin_mei, shohin_bunrui, hanbai_tanka, shiire_tanka, torokubi FROM shohin;
-- 用來彙總商品種類的表 CREATE TABLE shohinBunrui ( shohin_bunrui VARCHAR(32) NOT NULL, sum_hanbai_tanka INTEGER, sum_shiire_tanka INTEGER, PRIMARY KEY (shohin_bunrui) );
INSERT INTO shohinBunrui (shohin_bunrui, sum_hanbai_tanka, sum_shiire_tanka) SELECT shohin_bunrui, SUM(hanbai_tanka), SUM(shiire_tanka) FROM shohin GROUP BY shohin_bunrui;
SELECT * FROM shohinBunrui; |
法則4-3 |
INSERT語句的SELECT語句中,可以使用WHERE子句或者GROUP BY 子句等任何SQL語法(但使用ORDER BY子句並不會產生任何效果) |
4-2 資料的刪除(DELETE語句的使用方法)
刪除資料的方法,大體可以分為以下兩種 :
第一, DROP TABLE語句可以將表完全刪除,因此刪除之後再想插入資料,就必須使用CREATE TABLE語句重新建立一張表。
第二, DELETE語句會留下表(容器),而刪除表中的全部資料,因此只需要通過INSERT語句就可以再次向表中插入資料。
只能刪除表中全部資料的TERUNCASE語句 TRUNCASE <表名>;
與delete不同的是,truncate只能刪除表中的全部資料,而不能通過where子句指定條件來刪除部分資料。也正是因為它不能具體地控制刪除物件,所以其處理速度比delete要快的多。
DELETE語句的基本語法 |
-- DELETE FROM <表名>; DELETE FROM shohin; |
由於DELETE語句的物件是行而不是列,所以DELETE語句無法只刪除部分列的資料。因此,在DELETE語句中指定列名是錯誤的。當然,使用星號的寫法也是不對的(DELETE * FROM shohin;),同樣會出錯。
法則4-4 |
DELECT語句的刪除物件並不是表或者列,而是記錄(行)。 |
想要刪除部分資料行時,可以像SELECT語句那樣使用WHERE子句指定刪除條件。這種指定了刪除物件的DELETE語句稱為搜尋型DELETE.
指定刪除物件的DELETE語句(搜尋型DELECT) |
-- DELETE FROM <表名> WHERE <條件>;
DELETE FROM shohin WHERE hanbai_tanka >= 4000; |
與SELECT語句不同的是,DELETE語句中不能使用GROUP BY、HAVING和ORDER BY三類子句,而只能使用WHERE子句。原因很簡單,GROUP BY和HAVING是從表中選取資料時用來改變抽取資料形式的,而ORDER BY是用來指定取得結果顯示順序的。因此,在刪除表中資料時它們都起不到什麼作用。
法則4-5 |
可以通過WHERE子句指定物件條件來刪除部分資料。 |
4-3 資料的更新(UPDATE語句的使用方法)
UPDATE語句的基本語法 |
-- UPDATE <表名> SET <列名> = <表示式>;
UPDATE shohin SET torokubi = '2009-10-10';
SELECT * FROM shohin ORDER BY shohin_id; |
將更新物件的列和更新後的值都記述在SET子句中。
更新資料時也可以像DELETE語句那樣使用WHERE子句。這種指定更新物件的UPDATE語句稱為搜尋型UPDATE語句。
指定條件的UPDATE語句(搜尋型UPDATE) |
-- UPDATE <表名> SET <列名> = <表示式> WHERE <條件>;
UPDATE shohin SET hanbai_tanka = hanbai_tanka * 10 WHERE shohin_bunrui = '廚房用具';
SELECT * FROM shohin ORDER BY shohin_id; |
使用UPDATE也可以將列更新為NULL(該更新俗稱為NULL清空)。
使用NULL進行更新 |
UPDATE shohin SET torokubi = NULL WHERE shohin_id = '0008';
SELECT * FROM shohin ORDER BY shohin_id; |
和INSERT語句一樣,UPDATE語句也可以將NULL作為一個值來使用。
但是,只有未設定NOT NULL約束和主鍵約束的列才可以清空為NULL。如果將設定了上述約束的列更新為NULL,就會出錯,這點與INSERT語句相同。
法則4-6 |
使用UPDATE語句可以將值清空為NULL(但只限於未設定NOT NULL約束的列)。 |
UPDATE語句的SET子句支援同時將多個列作為更新物件。
多列更新 |
-- 使用逗號將列分隔排列 UPDATE shohin SET hanbai_tanka = hanbai_tanka * 10 WHERE shohin_bunrui = '廚房用具';
-- 將列用()括起來的列表形式 UPDATE shohin SET shiire_tanka = shiire_tanka / 2 WHERE shohin_bunrui = '廚房用具';
-- 建議使用這一種,使用逗號將列進行分隔排序的方法,這是通用的 UPDATE shohin SET hanbai_tanka = hanbai_tanka * 10, shiire_tanka = shiire_tanka / 2 WHERE shohin_bunrui = '廚房用具'; -- 部分dbms不支援下面這種寫法 UPDATE shohin SET (hanbai_tanka, shiire_tanka) = (hanbai_tanka * 10, shiire_tanka / 2) WHERE shohin_bunrui = '廚房用具'; |
4-4 事務
在RDBMS中,事務代表了對錶中資料進行更新的單位。簡單來講,事務就是需要在同一個處理單元中執行的一系列更新處理的集合。
4-7 |
事務是需要在同一個處理單元中執行的一系列更新處理的集合。 |
一個事務中包含多少個更新處理或者包含哪些處理,在DBMS中並沒有固定的標準。
使用事務開始語句和事務結束語句,將一系列DML語句(INSERT/UPDATE/DELETE語句)括起來,就實現了一個事務處理。
建立事務 |
/* 事務開始語句; DML語句1; DML語句2; DML語句3; . . . 事務結束語句(COMMIT或者ROLLBACK);
SQL server / PostgreSQL BEGIN TRANSACTION
mysql START TRANSACTION
oracle / DB2 無
*/
-- SQL server postgresql BEGIN TRANSACTION; UPDATE shohin SET hanbai_tanka = hanbai_tanka - 1000 WHERE shohin_mei = '運動T恤'; UPDATE shohin SET hanbai_tanka = hanbai_tanka + 1000 WHERE shohin_mei = 'T恤衫'; COMMIT;
-- mysql START TRANSACTION; UPDATE shohin SET hanbai_tanka = hanbai_tanka - 1000 WHERE shohin_mei = '運動T恤'; UPDATE shohin SET hanbai_tanka = hanbai_tanka + 1000 WHERE shohin_mei = 'T恤衫'; COMMIT;
-- oracle db2 UPDATE shohin SET hanbai_tanka = hanbai_tanka - 1000 WHERE shohin_mei = '運動T恤'; UPDATE shohin SET hanbai_tanka = hanbai_tanka + 1000 WHERE shohin_mei = 'T恤衫'; COMMIT;
/* 各個dbms事務的開始語句都不盡相同。其中Oracle和DB2並沒有定義特定的開始語句。 可能大家覺得這樣設計很巧妙,其實是因為標準sql中規定了 一種悄悄開始事務處理的方法。因此,即使經驗豐富的工程師也經常忽略事務處理開始的時點。
*/
-- SQL server postgresql BEGIN TRANSACTION; UPDATE shohin SET hanbai_tanka = hanbai_tanka - 1000 WHERE shohin_mei = '運動T恤'; UPDATE shohin SET hanbai_tanka = hanbai_tanka + 1000 WHERE shohin_mei = 'T恤衫'; ROLLBACK; |
COMMIT是提交事務包含的全部更新處理的結束指令。相當於檔案處理中的覆蓋儲存。一旦提交,就無法恢復到事務開始前的狀態了。因此,在提交之前一定要確認是否真的需要進行這些更新。
萬一由於誤操作提交了包含錯誤更新的事務,就只能重新回到重新建表、重新插入資料這樣繁瑣的老路上了。由於可能會造成無法恢復的後果,請大家一定要注意(特別是在執行DELETE語句的COMMIT時尤其小心)。
ROLLBACK是取消事務包含的全部更新處理的結束命令。相當於檔案處理中的放棄儲存。一旦回滾,資料庫就會回覆到事務開始之前的狀態。通常回滾並不會像提交那樣造成大規模的資料損失。
法則4-8 |
雖然我們可以不清楚事務開始的時點,但是在事務結束時一定要仔細進行確認。 |
DBMS的事務都遵循四種標準規格的約定。將這四種特定的首字母結合起來統稱為ACID特性。這些約定是所有DBMS都必須遵守的規則。
ACID特性 |
原子性是指在事務結束時,其中所包含的更新處理要麼全部執行,要麼完全不執行的特性。也就是要麼佔有一切要麼一無所有。從事務中途停止的角度去考慮,就能比較容易理解原子性的重要性了。由於使用者在一個事務中定義了兩條UPDATE語句,DBMS肯定不會只執行其中一條,否則就會對業務處理造成影響。
一致性指的是事務中包含的處理,要滿足資料庫提前設定的約束,如主鍵約束或者not null約束等。對事務來說,這些不合法的SQL會被回滾。也就是說這些SQL處理會被取消,不會執行。一致性也稱完整性。
隔離性指的是保證不同事務之間互不干擾的特性。該特性保證了事務之間不會互相巢狀。此外,在某個事務中進行的更改,在該事務結束之前,對其他事務而言是不可見的。因此,即使某個事務向表中添加了記錄,在沒有提交之前,其他事務是看不到新新增的記錄的。
永續性也可以稱為耐久性,指的是事務(不論是提交還是回滾)一旦結束,dbms會保證該時點的資料狀態得以儲存的特性。即使由於系統故障導致資料丟失,資料庫也一定能通過某種手段進行恢復。如果不能保證永續性,即使是正常提交結束的事務,一旦發生了系統故障,就會導致資料丟失,一切都需要從頭再來的後果。保證永續性的方法根據實現的不同而不同,其中最常見的就是將事務的執行記錄儲存到硬碟等儲存介質中(該執行記錄稱為日誌)。當發生故障時,可以通過日誌恢復到故障發生的狀態。 |