第11章_資料處理之增刪改
1. 插入資料
1.1 實際問題
解決方式:使用 INSERT 語句向表中插入資料。
1.2 方式1:VALUES的方式新增
使用這種語法一次只能向表中插入一條資料。
情況1:為表的所有欄位按預設順序插入資料
INSERT INTO 表名
VALUES (value1,value2,....);
值列表中需要為表的每一個欄位指定值,並且值的順序必須和資料表中欄位定義時的順序相同。
舉例:
INSERT INTO departments
VALUES (70, 'Pub', 100, 1700);
INSERT INTO departments VALUES (100, 'Finance', NULL, NULL);
情況2:為表的指定欄位插入資料
INSERT INTO 表名(column1 [, column2, …, columnn])
VALUES (value1 [,value2, …, valuen]);
為表的指定欄位插入資料,就是在INSERT語句中只向部分欄位中插入值,而其他欄位的值為表定義時的預設值。
在 INSERT 子句中隨意列出列名,但是一旦列出,VALUES中要插入的value1,....valuen需要與column1,...columnn列一一對應。如果型別不同,將無法插入,並且MySQL會產生錯誤。
舉例:
INSERT INTO departments(department_id, department_name) VALUES (80, 'IT');
情況3:同時插入多條記錄
INSERT語句可以同時向資料表中插入多條記錄,插入時指定多個值列表,每個值列表之間用逗號分隔開,基本語法格式如下:
INSERT INTO table_name
VALUES
(value1 [,value2, …, valuen]),
(value1 [,value2, …, valuen]),
……
(value1 [,value2, …, valuen]);
或者
INSERT INTO table_name(column1 [, column2, …, columnn]) VALUES (value1 [,value2, …, valuen]), (value1 [,value2, …, valuen]), …… (value1 [,value2, …, valuen]);
舉例:
mysql> INSERT INTO emp(emp_id,emp_name)
-> VALUES (1001,'shkstart'),
-> (1002,'atguigu'),
-> (1003,'Tom');
Query OK, 3 rows affected (0.00 sec)
Records: 3 Duplicates: 0 Warnings: 0
使用INSERT同時插入多條記錄時,MySQL會返回一些在執行單行插入時沒有的額外資訊,這些資訊的含義如下:
● Records:表明插入的記錄條數。
● Duplicates:表明插入時被忽略的記錄,原因可能是這些記錄包含了重複的主鍵值。
● Warnings:表明有問題的資料值,例如發生資料型別轉換。
一個同時插入多行記錄的INSERT語句等同於多個單行插入的INSERT語句,但是多行的INSERT語句在處理過程中
效率更高
。因為MySQL執行單條INSERT語句插入多行資料比使用多條INSERT語句快,所以在插入多條記錄時最好選擇使用單條INSERT語句的方式插入。
小結:
-
VALUES
也可以寫成VALUE
,但是VALUES是標準寫法。 -
字元和日期型資料應包含在單引號中。
1.3 方式2:將查詢結果插入到表中
INSERT還可以將SELECT語句查詢的結果插入到表中,此時不需要把每一條記錄的值一個一個輸入,只需要使用一條INSERT語句和一條SELECT語句組成的組合語句即可快速地從一個或多個表中向一個表中插入多行。
基本語法格式如下:
INSERT INTO 目標表名
(tar_column1 [, tar_column2, …, tar_columnn])
SELECT
(src_column1 [, src_column2, …, src_columnn])
FROM 源表名
[WHERE condition]
- 在 INSERT 語句中加入子查詢。
- 不必書寫 VALUES 子句。
- 子查詢中的值列表應與 INSERT 子句中的列名對應。
舉例:
INSERT INTO emp2
SELECT *
FROM employees
WHERE department_id = 90;
INSERT INTO sales_reps(id, name, salary, commission_pct)
SELECT employee_id, last_name, salary, commission_pct
FROM employees
WHERE job_id LIKE '%REP%';
2. 更新資料
- 使用 UPDATE 語句更新資料。語法如下:
UPDATE table_name
SET column1=value1, column2=value2, … , column=valuen
[WHERE condition]
-
可以一次更新多條資料。
-
如果需要回滾資料,需要保證在DML前,進行設定:SET AUTOCOMMIT = FALSE;
- 使用 WHERE 子句指定需要更新的資料。
UPDATE employees
SET department_id = 70
WHERE employee_id = 113;
- 如果省略 WHERE 子句,則表中的所有資料都將被更新。
UPDATE copy_emp
SET department_id = 110;
- 更新中的資料完整性錯誤
UPDATE employees
SET department_id = 55
WHERE department_id = 110;
說明:不存在 55 號部門
3. 刪除資料
- 使用 DELETE 語句從表中刪除資料
DELETE FROM table_name [WHERE <condition>];
table_name指定要執行刪除操作的表;“[WHERE
- 使用 WHERE 子句刪除指定的記錄。
DELETE FROM departments
WHERE department_name = 'Finance';
- 如果省略 WHERE 子句,則表中的全部資料將被刪除
DELETE FROM copy_emp;
- 刪除中的資料完整性錯誤
DELETE FROM departments
WHERE department_id = 60;
說明:You cannot delete a row that contains a primary key that is used as a foreign key in another table.
4. MySQL8新特性:計算列
什麼叫計算列呢?簡單來說就是某一列的值是通過別的列計算得來的。例如,a列值為1、b列值為2,c列不需要手動插入,定義a+b的結果為c的值,那麼c就是計算列,是通過別的列計算得來的。
在MySQL 8.0中,CREATE TABLE 和 ALTER TABLE 中都支援增加計算列。下面以CREATE TABLE為例進行講解。
舉例:定義資料表tb1,然後定義欄位id、欄位a、欄位b和欄位c,其中欄位c為計算列,用於計算a+b的值。
首先建立測試表tb1,語句如下:
CREATE TABLE tb1(
id INT,
a INT,
b INT,
c INT GENERATED ALWAYS AS (a + b) VIRTUAL
);
插入演示資料,語句如下:
INSERT INTO tb1(a,b) VALUES (100,200);
查詢資料表tb1中的資料,結果如下:
mysql> SELECT * FROM tb1;
+------+------+------+------+
| id | a | b | c |
+------+------+------+------+
| NULL | 100 | 200 | 300 |
+------+------+------+------+
1 row in set (0.00 sec)
更新資料中的資料,語句如下:
mysql> UPDATE tb1 SET a = 500;
Query OK, 0 rows affected (0.00 sec)
Rows matched: 1 Changed: 0 Warnings: 0
5. 綜合案例
# 1、建立資料庫test01_library
# 2、建立表 books,表結構如下:
欄位名 | 欄位說明 | 資料型別 |
---|---|---|
id | 書編號 | INT |
name | 書名 | VARCHAR(50) |
authors | 作者 | VARCHAR(100) |
price | 價格 | FLOAT |
pubdate | 出版日期 | YEAR |
note | 說明 | VARCHAR(100) |
num | 庫存 | INT |
# 3、向books表中插入記錄
# 1)不指定欄位名稱,插入第一條記錄
# 2)指定所有欄位名稱,插入第二記錄
# 3)同時插入多條記錄(剩下的所有記錄)
id | name | authors | price | pubdate | note | num |
---|---|---|---|---|---|---|
1 | Tal of AAA | Dickes | 23 | 1995 | novel | 11 |
2 | EmmaT | Jane lura | 35 | 1993 | joke | 22 |
3 | Story of Jane | Jane Tim | 40 | 2001 | novel | 0 |
4 | Lovey Day | George Byron | 20 | 2005 | novel | 30 |
5 | Old land | Honore Blade | 30 | 2010 | law | 0 |
6 | The Battle | Upton Sara | 30 | 1999 | medicine | 40 |
7 | Rose Hood | Richard haggard | 28 | 2008 | cartoon | 28 |
# 4、將小說型別(novel)的書的價格都增加5。
# 5、將名稱為EmmaT的書的價格改為40,並將說明改為drama。
# 6、刪除庫存為0的記錄。
# 7、統計書名中包含a字母的書
# 8、統計書名中包含a字母的書的數量和庫存總量
# 9、找出“novel”型別的書,按照價格降序排列
# 10、查詢圖書資訊,按照庫存量降序排列,如果庫存量相同的按照note升序排列
# 11、按照note分類統計書的數量
# 12、按照note分類統計書的庫存量,顯示庫存量超過30本的
# 13、查詢所有圖書,每頁顯示5本,顯示第二頁
# 14、按照note分類統計書的庫存量,顯示庫存量最多的
# 15、查詢書名達到10個字元的書,不包括裡面的空格
# 16、查詢書名和型別,其中note值為novel顯示小說,law顯示法律,medicine顯示醫藥,cartoon顯示卡通,joke顯示笑話
# 17、查詢書名、庫存,其中num值超過30本的,顯示滯銷,大於0並低於10的,顯示暢銷,為0的顯示需要無貨
# 18、統計每一種note的庫存量,併合計總量
# 19、統計每一種note的數量,併合計總量
# 20、統計庫存量前三名的圖書
# 21、找出最早出版的一本書
# 22、找出novel中價格最高的一本書
# 23、找出書名中字數最多的一本書,不含空格
答案:
#1、建立資料庫test01_library
CREATE DATABASE IF NOT EXISTS test01_library CHARACTER SET 'utf8';
#指定使用哪個資料庫
USE test01_library;
#2、建立表 books
CREATE TABLE books(
id INT,
name VARCHAR(50),
`authors` VARCHAR(100) ,
price FLOAT,
pubdate YEAR ,
note VARCHAR(100),
num INT
);
#3、向books表中插入記錄
# 1)不指定欄位名稱,插入第一條記錄
INSERT INTO books
VALUES(1,'Tal of AAA','Dickes',23,1995,'novel',11);
# 2)指定所有欄位名稱,插入第二記錄
INSERT INTO books (id,name,`authors`,price,pubdate,note,num)
VALUES(2,'EmmaT','Jane lura',35,1993,'Joke',22);
# 3)同時插入多條記錄(剩下的所有記錄)
INSERT INTO books (id,name,`authors`,price,pubdate,note,num) VALUES
(3,'Story of Jane','Jane Tim',40,2001,'novel',0),
(4,'Lovey Day','George Byron',20,2005,'novel',30),
(5,'Old land','Honore Blade',30,2010,'Law',0),
(6,'The Battle','Upton Sara',30,1999,'medicine',40),
(7,'Rose Hood','Richard haggard',28,2008,'cartoon',28);
# 4、將小說型別(novel)的書的價格都增加5。
UPDATE books SET price=price+5 WHERE note = 'novel';
# 5、將名稱為EmmaT的書的價格改為40,並將說明改為drama。
UPDATE books SET price=40,note='drama' WHERE name='EmmaT';
# 6、刪除庫存為0的記錄。
DELETE FROM books WHERE num=0;
# 7、統計書名中包含a字母的書
SELECT * FROM books WHERE name LIKE '%a%';
# 8、統計書名中包含a字母的書的數量和庫存總量
SELECT COUNT(*),SUM(num) FROM books WHERE name LIKE '%a%';
# 9、找出“novel”型別的書,按照價格降序排列
SELECT * FROM books WHERE note = 'novel' ORDER BY price DESC;
# 10、查詢圖書資訊,按照庫存量降序排列,如果庫存量相同的按照note升序排列
SELECT * FROM books ORDER BY num DESC,note ASC;
# 11、按照note分類統計書的數量
SELECT note,COUNT(*) FROM books GROUP BY note;
# 12、按照note分類統計書的庫存量,顯示庫存量超過30本的
SELECT note,SUM(num) FROM books GROUP BY note HAVING SUM(num)>30;
# 13、查詢所有圖書,每頁顯示5本,顯示第二頁
SELECT * FROM books LIMIT 5,5;
# 14、按照note分類統計書的庫存量,顯示庫存量最多的
SELECT note,SUM(num) sum_num FROM books GROUP BY note ORDER BY sum_num DESC LIMIT 0,1;
# 15、查詢書名達到10個字元的書,不包括裡面的空格
SELECT * FROM books WHERE CHAR_LENGTH(REPLACE(name,' ',''))>=10;
/*
16、查詢書名和型別,
其中note值為 novel顯示小說,law顯示法律,medicine顯示醫藥,cartoon顯示卡通,joke顯示笑話
*/
SELECT name AS "書名" ,note, CASE note
WHEN 'novel' THEN '小說'
WHEN 'law' THEN '法律'
WHEN 'medicine' THEN '醫藥'
WHEN 'cartoon' THEN '卡通'
WHEN 'joke' THEN '笑話'
END AS "型別"
FROM books;
# 17、查詢書名、庫存,其中num值超過30本的,顯示滯銷,大於0並低於10的,顯示暢銷,為0的顯示需要無貨
SELECT name,num,CASE
WHEN num>30 THEN '滯銷'
WHEN num>0 AND num<10 THEN '暢銷'
WHEN num=0 THEN '無貨'
ELSE '正常'
END AS "庫存狀態"
FROM books;
# 18、統計每一種note的庫存量,併合計總量
SELECT IFNULL(note,'合計總庫存量') AS note,SUM(num) FROM books GROUP BY note WITH ROLLUP;
# 19、統計每一種note的數量,併合計總量
SELECT IFNULL(note,'合計總數') AS note,COUNT(*) FROM books GROUP BY note WITH ROLLUP;
# 20、統計庫存量前三名的圖書
SELECT * FROM books ORDER BY num DESC LIMIT 0,3;
# 21、找出最早出版的一本書
SELECT * FROM books ORDER BY pubdate ASC LIMIT 0,1;
# 22、找出novel中價格最高的一本書
SELECT * FROM books WHERE note = 'novel' ORDER BY price DESC LIMIT 0,1;
# 23、找出書名中字數最多的一本書,不含空格
SELECT * FROM books ORDER BY CHAR_LENGTH(REPLACE(name,' ','')) DESC LIMIT 0,1;