与 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;
发布了46 篇原创文章 · 获赞 42 · 访问量 5万+

猜你喜欢

转载自blog.csdn.net/Phplayers/article/details/103454903