與 MySQL 的零距離接觸(4~5:數據基礎操作 - 增刪改查)

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;

  1. 子查詢指嵌套在【查詢內部】,且必須始終出現在【圓括號內】
  2. 子查詢可以包含多個關鍵字或者條件,如DISTINCT,GROUP BY,ORDER BY,LIMIT,函數等
  3. 子查詢的外層查詢可以是:【SELECT,INSERT,UPDATE,SET或DO】
  4. 子查詢可以返回值:標量、一行、一列或者子查詢。

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/SOMEALL 的運算

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. 先確定連接關係,如表1 INNER JOIN 表2,
  2. 然再確定連接條件,如ON 表1.name=表2.name
  3. 確定要把表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;

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章