SQL基礎-第4章 資料更新
4-1 資料的插入(INSERT語句的使用方法)
什麼是INSERT
-- 建立ProductIns表的CREATE TABLE語句 CREATE TABLE ProductIns (product_id CHAR(4) NOT NULL, product_name VARCHAR(100) NOT NULL, product_type VARCHAR(32) NOT NULL, sale_price INTEGER DEFAULT 0, purchase_price INTEGER , regist_date DATE , PRIMARY KEY (product_id)) DEFAULT CHARSET=utf8;
INSERT語句的基本語法
INSERT INTO <表名> (列1, 列2, 列3, ……) VALUES (值1, 值2, 值3, ……);
-- 向表中插入一行資料
INSERT INTO ProductIns (product_id, product_name, product_type, sale_price, purchase_price, regist_date) VALUES ('0001', 'T恤衫', '衣服', 1000, 500, '2009-09-20');
原則上,執行一次INSERT語句會插入一行資料
列清單的省略
省略列清單
-- 包含列清單 INSERT INTO ProductIns (product_id, product_name, product_type, sale_price, purchase_price, regist_date) VALUES ('0005', '高壓鍋', '廚房用具', 6800, 5000, '2009-01-15'); -- 省略列清單 INSERT INTO ProductIns VALUES ('0005', '高壓鍋', '廚房用具', 6800, 5000, '2009-01-15');
插入NULL
-- 向purchase_price列中插入NULL
INSERT INTO ProductIns (product_id, product_name, product_type, sale_price, purchase_price, regist_date) VALUES ('0006', '叉子', '廚房用具', 500, NULL, '2009-09-20');
插入預設值
-- 建立ProductIns表的CREATE TABLE語句(節選) CREATE TABLE ProductIns( product_id CHAR(4) NOT NULL, (略) sale_price INTEGER DEFAULT 0, -- 銷售單價的預設值設定為0; (略) PRIMARY KEY (product_id) );
-
通過顯式方法插入預設值
- 在 VALUES 子句中指定 DEFAULT 關鍵字
-
通過隱式方法插入預設值
- 在列清單和 VALUES 中省略設定了預設值的列就可以
省略INSERT語句中的列名,就會自動設定為該列的預設值(沒有預設值時會設定為NULL)。
-- 通過顯式方法設定預設值
INSERT INTO ProductIns (product_id, product_name, product_type, sale_price, purchase_price, regist_date) VALUES ('0007', '擦菜板', '廚房用具', DEFAULT, 790, '2009-04-28');
-- 通過隱式方法設定預設值
INSERT INTO ProductIns (product_id, product_name, product_type, purchase_price, regist_date) VALUES ('0007', '擦菜板', '廚房用具', 790, '2009-04-28');
未設定預設值的情況
-- 省略purchase_price列(無約束):會賦予“NULL”
INSERT INTO ProductIns (product_id, product_name, product_type, sale_price, regist_date) VALUES ('0008', '圓珠筆', '辦公用品', 100, '2009-11-11');
-- 省略product_name列(設定了NOT NULL約束):錯誤!
INSERT INTO ProductIns (product_id, product_type, sale_price, purchase_price, regist_date) VALUES ('0009', '辦公用品', 1000, 500, '2009-12-12');
從其他表中複製資料
-- 用來插入資料的商品複製表
CREATE TABLE ProductCopy
(product_id CHAR(4) NOT NULL,
product_name VARCHAR(100) NOT NULL,
product_type VARCHAR(32) NOT NULL,
sale_price INTEGER ,
purchase_price INTEGER ,
regist_date DATE ,
PRIMARY KEY (product_id))
DEFAULT CHARSET=utf8;
INSERT ... SELECT語句
-- 將商品表中的資料複製到商品複製表中
INSERT INTO ProductCopy (product_id, product_name, product_type, sale_price, purchase_price, regist_date)
SELECT product_id, product_name, product_type, sale_price, purchase_price, regist_date
FROM Product;
建立ProductType表的CREATE TABLE語句
-- 根據商品種類進行彙總的表 ;
CREATE TABLE ProductType
(product_type VARCHAR(32) NOT NULL,
sum_sale_price INTEGER ,
sum_purchase_price INTEGER ,
PRIMARY KEY (product_type))
DEFAULT CHARSET=utf8;
-- 插入其他表中資料合計值的INSERT ... SELECT語句
INSERT INTO ProductType (product_type, sum_sale_price, sum_purchase_price)
SELECT product_type, SUM(sale_price), SUM(purchase_price)
FROM Product
GROUP BY product_type;
4-2 資料的刪除(DELETE語句的使用方法)
DROP-TABLE語句和DELETE語句
- DROP TABLE 語句可以將表完全刪除
- DELETE 語句會留下表(容器),而刪除表中的全部資料
DELETE語句的基本語法
DELETE FROM <表名>;
清空Product表
DELETE FROM Product;
DELETE語句的刪除物件並不是表或者列,而是記錄(行)。
指定刪除物件的DELETE語句(搜尋型DELETE)
刪除部分資料行的搜尋型DELETE
DELETE FROM <表名>
WHERE <條件>;
可以通過WHERE子句指定物件條件來刪除部分資料。
與 SELECT 語句不同的是, DELETE 語句中不能使用 GROUP BY、HAVING 和ORDER BY 三類子句,而只能使用WHERE 子句。
-- 刪除銷售單價( sale_price)大於等於4000日元的資料
DELETE FROM Product
WHERE sale_price >= 4000;
4-3 資料的更新(UPDATE語句的使用方法)
UPDATE語句的基本語法
改變表中資料的UPDATE語句
UPDATE <表名>
SET <列名> = <表示式>;
-- 將登記日期全部更新為“2009-10-10”
UPDATE Product
SET regist_date = '2009-10-10';
指定條件的UPDATE語句(搜尋型UPDATE)
更新部分資料行的搜尋型UPDATE
UPDATE <表名>
SET <列名> = <表示式>
WHERE <條件>;
-- 將商品種類為廚房用具的記錄的銷售單價更新為原來的10倍
UPDATE Product
SET sale_price = sale_price * 10
WHERE product_type = '廚房用具';
使用NULL進行更新
使用UPDATE語句可以將值清空為NULL(但只限於未設定NOT NULL約束的列)。
-- 將商品編號為0008的資料(圓珠筆)的登記日期更新為NULL
UPDATE Product
SET regist_date = NULL
WHERE product_id = '0008';
多列更新
能夠正確執行的繁瑣的UPDATE語句
-- 一條UPDATE語句只更新一列
UPDATE Product
SET sale_price = sale_price * 10
WHERE product_type = '廚房用具';
UPDATE Product
SET purchase_price = purchase_price / 2
WHERE product_type = '廚房用具';
方法①:程式碼清單4-19 將程式碼清單4-18的處理合併為一條UPDATE語句
-- 使用逗號對列進行分隔排列
UPDATE Product
SET sale_price = sale_price * 10,
purchase_price = purchase_price / 2
WHERE product_type = '廚房用具';
方法②:程式碼清單4-20 將程式碼清單4-18的處理合併為一條UPDATE語句 (mysql不支援)
-- 將列用()括起來的清單形式
UPDATE Product
SET (sale_price, purchase_price) = (sale_price * 10, purchase_price / 2)
WHERE product_type = '廚房用具';
4-4 事務
什麼是事務
事務就是需要在同一個處理單元中執行的一系列更新處理的集合。
建立事務
事務的語法
事務開始語句;
DML語句①;
DML語句②;
DML語句③;
...
事務結束語句( COMMIT或者ROLLBACK) ;
- COMMIT——提交處理
- COMMIT 是提交事務包含的全部更新處理的結束指令,相當於檔案處理中的覆蓋儲存
- COMMIT 是提交事務包含的全部更新處理的結束指令,相當於檔案處理中的覆蓋儲存
雖然我們可以不清楚事務開始的時間點,但是在事務結束時一定要仔細進行確認
- ROLLBACK——取消處理
- ROLLBACK 是取消事務包含的全部更新處理的結束指令,相當於檔案處理中的放棄儲存。
- ROLLBACK 是取消事務包含的全部更新處理的結束指令,相當於檔案處理中的放棄儲存。
START TRANSACTION;
-- 將運動T恤的銷售單價降低1000日元
UPDATE Product
SET sale_price = sale_price - 1000
WHERE product_name = '運動T恤';
-- 將T恤衫的銷售單價上浮1000日元
UPDATE Product
SET sale_price = sale_price + 1000
WHERE product_name = 'T恤衫';
COMMIT;
事務回滾的例子
START TRANSACTION;
-- 將運動T恤的銷售單價降低1000日元
UPDATE Product
SET sale_price = sale_price - 1000
WHERE product_name = '運動T恤';
-- 將T恤衫的銷售單價上浮1000日元
UPDATE Product
SET sale_price = sale_price + 1000
WHERE product_name = 'T恤衫';
ROLLBACK;
ACID特性
- 原子性(Atomicity)
- 原子性是指在事務結束時,其中所包含的更新處理要麼全部執行,要麼完全不執行,也就是要麼佔有一切要麼一無所有。
- 一致性(Consistency)
- 一致性指的是事務中包含的處理要滿足資料庫提前設定的約束,如主鍵約束或者 NOT NULL 約束等。
- 隔離性(Isolation)
- 隔離性指的是保證不同事務之間互不干擾的特性。該特性保證了事務之間不會互相巢狀。
- 永續性(Durability)
- 永續性也可以稱為耐久性,指的是在事務(不論是提交還是回滾)結束後, DBMS 能夠保證該時間點的資料狀態會被儲存的特性。
練習題
4.1 A 先生在自己的計算機(電腦)上,使用 CREATE TABLE 語句創建出了一張空的 Product(商品)表,並執行了如下的 SQL 語句向其中插入資料。
START TRANSACTION;
INSERT INTO Product VALUES ('0001', 'T恤衫', '衣服', 1000, 500, '2008-09-20');
INSERT INTO Product VALUES ('0002', '打孔器', '辦公用品', 500, 320, '2008-09-11');
INSERT INTO Product VALUES ('0003', '運動T恤', '衣服', 4000, 2800, NULL);
緊接著,B 先生使用其他的計算機連線上該資料庫,執行了如下 SELECT 語句。這時 B 先生能得到怎樣的查詢結果呢?
SELECT * FROM Product;
提示:如果可以使用DELETE語句,就可以對通過CREATE TABLE語句創建出的空表執行該操作了。
沒有一行資料,事務沒有提交
CREATE TABLE Product
(product_id CHAR(4) NOT NULL,
product_name VARCHAR(100) NOT NULL,
product_type VARCHAR(32) NOT NULL,
sale_price INTEGER ,
purchase_price INTEGER ,
regist_date DATE ,
PRIMARY KEY (product_id)) DEFAULT CHARSET=utf8;
DELETE FROM Product;
INSERT INTO Product VALUES ('0001', 'T恤衫', '衣服', 1000, 500, '2008-09-20');
INSERT INTO Product VALUES ('0002', '打孔器', '辦公用品', 500, 320, '2008-09-11');
INSERT INTO Product VALUES ('0003', '運動T恤', '衣服', 4000, 2800, NULL);
SELECT * FROM Product;
4.2 有一張包含 3 條記錄的 Product 表。
使用如下的 INSERT 語句複製這 3 行資料,應該就能夠將表中的資料增加為 6 行。請說出該語句的執行結果。
INSERT INTO Product SELECT * FROM Product;
Duplicate entry '0001' for key 'PRIMARY'
4.3 以練習 4.2 中的 Product 表為基礎,再建立另外一張包含利潤列的新表ProductMargin(商品利潤)。
-- 商品利潤表
CREATE TABLE ProductMargin
(product_id CHAR(4) NOT NULL,
product_name VARCHAR(100) NOT NULL,
sale_price INTEGER,
purchase_price INTEGER,
margin INTEGER,
PRIMARY KEY(product_id));
請寫出向上述表中插入如下資料的 SQL 語句,其中的利潤可以簡單地通過對 Product 表中的資料進行計算(銷售單價 - 進貨單價)得出。
product_id product_name sale_price purchase_price margin
0001 T恤衫 1000 500 500
0002 打孔器 500 320 180
0003 運動T恤 4000 2800 1200
CREATE TABLE ProductMargin
(product_id CHAR(4) NOT NULL,
product_name VARCHAR(100) NOT NULL,
sale_price INTEGER,
purchase_price INTEGER,
margin INTEGER,
PRIMARY KEY(product_id))
DEFAULT CHARSET=utf8;
INSERT INTO ProductMargin(product_id, product_name, sale_price, purchase_price, margin)
SELECT product_id, product_name, sale_price, purchase_price, sale_price - purchase_price
FROM Product;
4.4 對練習 4.3 中的 ProductMargin 表的資料進行如下更改。
- 將運動 T 恤的銷售單價從 4000 日元下調至 3000 日元。
- 根據上述結果再次計算運動 T 恤的利潤。
更改後的ProductMargin表如下所示。請寫出能夠實現該變更的SQL語句
UPDATE ProductMargin
SET sale_price = 3000
WHERE product_name = '運動T恤';
UPDATE ProductMargin
SET margin = sale_price - purchase_price
WHERE product_name = '運動T恤';