MySQL 中最基本也是最重要的是 操作數據表中的記錄 ,也就是對數據表中的記錄進行增刪改查操作。
INSERT
添加記錄的三種方式:
1. INSERT ... VALUES ...
INSERT [INTO] table_name [(column_name,...)] {VALUES|VALUE} ({expr(表達式)|DEFAULT(默認值)},...),(...),...;
# 若省略列名則所有列要依次賦值
# 對於自動編號的字段,插入“NULL”或“DEFAULT”系統將自動依次遞增編號;
# 對於有默認值的字段,可以插入“DEFAULT”表示使用默認值;
# 可同時插入多條記錄,多條記錄括號間用逗號“,”隔開.
2. INSERT ... SET ...
INSERT INTO tbl_name SET col_name = {expr | DEFAULT},...
# 該語句與第一種方法的區別是該語句可以使用子查詢(SubQuery)
# 該語句一次只能插入一條記錄;
3. INSERT ... SELECT ...
INSERT INTO tbl_name[(col_name)] SELECT...
# eg: INSERT INTO tb1(name) SELECT name FROM tb2 WHERE id > 10;
後續…
DELETE
刪除記錄有兩種方法,單表刪除與多表刪除
1. 單表刪除
DELETE FROM 表名 [WHERE where_condition]
# 如果不寫where語句限定條件,那麼就會刪除所有數據
# 如果刪除了某條記錄,添加表單時,具有AUTO_INCREMENT的字段其值會在現有最大值的基礎上順延下去
2. 多表刪除
略
# eg: DELETE t1 FROM tdb_goods AS t1 LEFT JOIN (SELECT goods_id,goods_name FROM tdb_goods GROUP BY goods_name HAVING count(goods_name) >= 2 ) AS t2 ON t1.goods_name = t2.goods_name WHERE t1.goods_id > t2.goods_id;
後續…
UPDATE
修改記錄也有兩種方法,單表更新與鏈表更新
1. 單表更新
UPDATE table_reference SET col_name1={expr1|DEFAULT} [,col_name2={expr2|DEFAULT}]... [WHERE where_condition]
# 如果不寫where語句限定條件,那麼就會更新所有數據
2. 鏈表更新
略
# eg:UPDATE tdb_goods INNER JOIN tdb_goods_cates ON goods_cate = cate_name SET goods_cate = cate_id ;
SELECT
80% 我們都是在使用 select 操作語句
SELECT [ALL | DISTINCT] column1[,column2]
FROM table1[,table2]
[WHERE "conditions"]
[GROUP BY "column-list"]
[HAVING "conditions]
[ORDER BY "column-list" [ASC | DESC] ]
1. select_expr
# 版本號
SELECT VERSION();
# 表達式
SELECT 1+1;
# 上面的栗子說明,select 不一定需要添加數據表,只要表達式即可完成查詢動作!
2. [AS]
SELECT column_name AS alias_name FROM table_name
# [AS] 可以省略,但不建議省略,聯表查詢時別名很重要
3. WHERE
WHERE 列 運算符 值
4 . GROUP BY
[GROUP BY{col_name|position} [ASC|DESC],...]
# 對查詢結果進行分組,分組的條件字段,字段值相同的就是一組
5. HAVING
[HAVING where_condition]
# 分組條件 or1 : HAVING後的字段出現在SELECT所查詢的字段中;
# 分組條件 or2 : 聚合函數
6. ORDER BY
[ORDER BY [col_name | expr | position } [ASC|DESC],...]
# 多個條件時,如果第一個條件 還不足排序 就拿下一個條件在原來的基礎上在進行一次排序,若第一個字段已滿足排序,則忽略後面的字段
7. LIMIT
[LIMIT {[offset,]row_count|row_count OFFSET offset}]
# offset:偏移量,從 零 開始
# row_count:返回結果的數目
子查詢
子查詢簡介
SELECT * FROM t1 WHERE column1 = (SELECT column1 FROM t2);
SELECT * FROM t1 … 被稱爲外查詢 Outer Query ,(SELECT column1 FROM t2); 被稱爲子查詢 Sub Query;
- 子查詢指嵌套在【查詢內部】,且必須始終出現在【圓括號內】
- 子查詢可以包含多個關鍵字或者條件,如DISTINCT,GROUP BY,ORDER BY,LIMIT,函數等
- 子查詢的外層查詢可以是:【SELECT,INSERT,UPDATE,SET或DO】
- 子查詢可以返回值:標量、一行、一列或者子查詢。
1 . 由比較運算符引發的子查詢
1.1 使用子查詢獲取商品價格大於平均價格的商品,並且按價格降序排序:
SELECT goods_id,goods_name,goods_price FROM tdb_goods
WHERE goods_price > (SELECT ROUND(AVG(goods_price),2) AS avg_price FROM tdb_goods)
ORDER BY goods_price DESC;
# ROUND 四捨五入取值,AVG 平均值;
1.2 查詢價格大於或等於”超級本”價格的商品,並且按價格降序排列,子查詢 #SELECT goods_price FROM tdb_goods WHERE goods_cate = ‘超級本’ 返回結果有 3 個結果,如果僅使用 > ,無法確定是大於 3 個結果值的最大值還是大於 3 個結果值的最小值,這裏需要引入 ANY/SOME 和 ALL 的運算;
SELECT goods_id,goods_name,goods_price FROM tdb_goods
WHERE goods_price = ANY(SELECT goods_price FROM tdb_goods WHERE goods_cate = '超級本')
ORDER BY goods_price DESC;
# ANY/SOME 是任何一個符合條件,ALL是全部符合條件;
2 . 由 [ NOT ] IN 引發的子查詢
[NOT] IN引起的子查詢:字段 [NOT] IN(value1,vaule2…),可查詢字段是否在括號內的值中存在,並返回一個布爾值,也因此可用於子查詢,因爲select也會返回一個結果集。
SELECT goods_id,goods_name,goods_price FROM tdb_goods
WHERE goods_price IN (SELECT goods_price FROM tdb_goods WHERE goods_cate = ‘超級本’)
ORDER BY goods_price DESC;
# ANY 或 SOME 等價於 IN,NOT IN 相當於 != ALL 或者 <> ALL —— 不等於、不包含。
3 . [NOT] EXISTS引起的子查詢
如果子查詢返回至少一行數據,則exists 返回 true,反之 返回 false
where [NOT] EXISTS(select ….)類似於where 字段 [NOT] IN(select ….),但側重點不一樣,EXISTS側重於select是否返回了語句,如果返回了數據,則該行就是true;
SELECT * FROM tdb_goods WHERE EXISTS(SELECT goods_id FROM test WHERE goods_id = t_id)
4 . INSERT … SELECT ...
將分組結果寫入到 tdb_goods_cates 數據表
INSERT tdb_goods_cates (cate_name) SELECT goods_cate FROM tdb_goods GROUP BY goods_cate;
5. 多表更新
UPDATE 表名1 {[INNER | CROSS ] JOIN|{LEFT|RIGHT} [OUTER] JOIN} 對應表名2 ON 對應條件 SET 字段名1={expr1 | DEFAULT} [,字段名2={expr2 | DEFAULT}]... [WHERE where_condition]
更新過程:
- 先確定連接關係,如表1 INNER JOIN 表2,
- 然再確定連接條件,如ON 表1.name=表2.name
- 確定要把表1的字段改成表2的哪個字段,SET 字段=…,其中①和②是表的連接
通過tdb_goods_cates數據表來更新tdb_goods表
UPDATE tdb_goods INNER JOIN tdb_goods_cates ON goods_cate = cate_name
SET goods_cate = cate_id ;
多表更新之一步到位
建表、查詢、寫入三合一:CREATE和SELECT語句結合,需注意,select返回的字段,如果在CREATE的表中不存在,那麼就會自動創建該字段並寫入信息,而如果已有該字段,就覆蓋並寫入該字段信息(相當於改變該字段的位置),如表中有a,b,c字段,如果select b,d,那麼表中字段順序會變成acbd,並且bd被寫入select的值。
如:通過CREATE…SELECT來創建數據表並且同時寫入記錄
CREATE TABLE tdb_goods_brands (
brand_id SMALLINT UNSIGNED PRIMARY KEY AUTO_INCREMENT,
brand_name VARCHAR(40) NOT NULL
)
SELECT brand_name FROM tdb_goods GROUP BY brand_name;
使用新表數據更新商品表數據:
UPDATE tdb_goods AS g INNER JOIN tdb_goods_brands AS b ON g.brand_name = b.brand_name
SET g.brand_name = b.brand_id;
注意:這裏必須使用到別名,因爲兩個表的字段名稱相同;
join 連接
SQL 在 select 、多表跟新、多表刪除時支持 JOIN 操作!連接需要考慮的是參照關係,誰參照誰這個就非常重要!
類型:
- INNER JOIN 內連接,只顯示符合連接條件的記錄
- RIGHT JOIN 右表全部加左表交集,沒有項爲NULL
- LEFT JOIN 構建臨時表時會先創建所有表1的值,再把符合條件的表2的行併入
查詢所有商品的詳細信息爲例:
內連接(JOIN | CROSS JOIN | INNER JOIN)
SELECT goods_id,goods_name,cate_name,brand_name,goods_price FROM tdb_goods AS g
INNER JOIN tdb_goods_cates AS c ON g.cate_id = c.cate_id
INNER JOIN tdb_goods_brands AS b ON g.brand_id = b.brand_id\G;
左外連接(LEFT JOIN)
SELECT goods_id,goods_name,cate_name,brand_name,goods_price FROM tdb_goods AS g
LEFT JOIN tdb_goods_cates AS c ON g.cate_id = c.cate_id
LEFT JOIN tdb_goods_brands AS b ON g.brand_id = b.brand_id\G;
右外連接(RIGHT JOIN)
SELECT goods_id,goods_name,cate_name,brand_name,goods_price FROM tdb_goods AS g
RIGHT JOIN tdb_goods_cates AS c ON g.cate_id = c.cate_id
RIGHT JOIN tdb_goods_brands AS b ON g.brand_id = b.brand_id\G;
# 這裏使使用ON關鍵字來設定連接條件,也可以使用WHERE來代替,通常使用ON關鍵字來設定連接條件,使用WHERE關鍵字進行結果集記錄的過濾。
無限分類的數據表設計
CREATE TABLE tdb_goods_types(
type_id SMALLINT UNSIGNED PRIMARY KEY AUTO_INCREMENT,
type_name VARCHAR(20) NOT NULL,
parent_id SMALLINT UNSIGNED NOT NULL DEFAULT 0
);
— 查找所有分類及其父類
SELECT s.type_id,s.type_name,p.type_name
FROM tdb_goods_types AS s
LEFT JOIN tdb_goods_types AS p
ON s.parent_id = p.type_id;
— 查找所有分類及其子類
SELECT s.type_id,s.type_name,p.type_name
FROM tdb_goods_types AS s
LEFT JOIN tdb_goods_types AS p
ON s.parent_id = p.type_id;
— 查找所有分類及其子類的數目
SELECT p.type_id,p.type_name,count(s.type_name) AS children_count
FROM tdb_goods_types AS p
LEFT JOIN tdb_goods_types AS s ON s.parent_id = p.type_id
GROUP BY p.type_name
ORDER BY p.type_id;
— 爲tdb_goods_types添加child_count字段
ALTER TABLE tdb_goods_types
ADD child_count MEDIUMINT UNSIGNED NOT NULL DEFAULT 0;
— INSERT … SELECT實現複製
INSERT tdb_goods(goods_name,cate_id,brand_id)
SELECT goods_name,cate_id,brand_id
FROM tdb_goods
WHERE goods_id IN (19,20);
— 查找重複記錄
SELECT goods_id,goods_name FROM tdb_goods
GROUP BY goods_name
HAVING count(goods_name) >= 2;
— 刪除重複記錄
DELETE t1 FROM tdb_goods AS t1
LEFT JOIN (SELECT goods_id,goods_name FROM tdb_goods GROUP BY goods_name HAVING count(goods_name) >= 2 ) AS t2
ON t1.goods_name = t2.goods_name WHERE t1.goods_id > t2.goods_id;