1. 程式人生 > 其它 >SQL基礎-第4章 資料更新

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語句

  1. DROP TABLE 語句可以將表完全刪除
  2. 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 是提交事務包含的全部更新處理的結束指令,相當於檔案處理中的覆蓋儲存

雖然我們可以不清楚事務開始的時間點,但是在事務結束時一定要仔細進行確認

  • 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 表的資料進行如下更改。

  1. 將運動 T 恤的銷售單價從 4000 日元下調至 3000 日元。
  2. 根據上述結果再次計算運動 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恤';