MySQL之表的记录操作

525 阅读5分钟

这是我参与更文挑战的第19天,活动详情查看: 更文挑战

微信公众号搜索【程序媛小庄】,关注半路出家的程序媛如何靠python开发养家糊口~

前言

存数据不是目的,目的是能够将存起来的数据取出来或者查出来,并且能够对数据进行增删改查操作,本文将详细介绍表中记录的增删改查操作。对记录的操作属于DML数据库操作语言,可以通过SQL实现对数据的操作,包括实现向表中插入数据(insert),对表中数据进行更新(update),删除表中数据(delete)以及查询数据(select)。

增 - insert

表准备

create table info ( 
	id int primary key auto_increment, 
	name varchar(6), 
	age int, 
	gender enum ( 'male', 'female' ) defaule 'male' 
	);

最标准的insert语句

-- INSERT INTO 表名(字段1, 字段2,...) VALUES (字段1对应的值, 字段2对应的值...);
mysql> insert into info(name, age, gender) values ('xu', 18, 'male');

mysql> select * from info;
+----+------+------+--------+
| id | NAME | age  | gender |
+----+------+------+--------+
|  1 | xu   |   18 | male   |
+----+------+------+--------+
1 row in set (0.00 sec)

省事的写法,按照所有字段顺序进行插入数据

-- INSERT INTO 表名 VALUES (字段1对应的值, 字段2对应的值...);
mysql> insert into info values (2, 'lili', 20, 'female');
Query OK, 1 row affected (0.00 sec)

mysql> select * from info;
+----+------+------+--------+
| id | NAME | age  | gender |
+----+------+------+--------+
|  1 | xu   |   18 | male   |
|  2 | lili |   20 | female |
+----+------+------+--------+
2 rows in set (0.00 sec)
 

针对性的录入数据

-- INSERT INTO 表名 (字段1, 字段2...) VALUES (字段1对应的值, 字段2对应的值...)
mysql> insert into info (name, age) values ('jack', 30);
Query OK, 1 row affected (0.00 sec)

mysql> select * from info;
+----+------+------+--------+
| id | NAME | age  | gender |
+----+------+------+--------+
|  1 | xu   |   18 | male   |
|  2 | lili |   20 | female |
|  3 | jack |   30 | male   |
+----+------+------+--------+
3 rows in set (0.00 sec)

同时录入多行数据

-- INSERT INTO 表名 (字段1, 字段2...) VALUES (字段1对应的值, 字段2对应的值...), (字段1对应的值, 字段2对应的值...)...;
mysql> insert into info (name, age) values ('python', 30),('java', 40),('go', 50);
Query OK, 3 rows affected (0.00 sec)
Records: 3  Duplicates: 0  Warnings: 0

mysql> select * from info;
+----+--------+------+--------+
| id | NAME   | age  | gender |
+----+--------+------+--------+
|  1 | xu     |   18 | male   |
|  2 | lili   |   20 | female |
|  3 | jack   |   30 | male   |
|  4 | python |   30 | male   |
|  5 | java   |   40 | male   |
|  6 | go     |   50 | male   |
+----+--------+------+--------+
6 rows in set (0.00 sec)

删 - delete

删除操作一定要慎重慎重再慎重!!!!

-- 删除表中的所有数据,但是主键的自增不会停止
delete from 表名;  

-- 清空表数据并重置主键
truncate 表名;  

-- 删除表中某一条或几条数据:delete from 表名 where 条件; (where条件在介绍查询时会详细介绍)
mysql> delete from info where id=1;
Query OK, 1 row affected (0.00 sec)

mysql> select * from info;
+----+--------+------+--------+
| id | NAME   | age  | gender |
+----+--------+------+--------+
|  2 | lili   |   20 | female |
|  3 | jack   |   30 | male   |
|  4 | python |   30 | male   |
|  5 | java   |   40 | male   |
|  6 | go     |   50 | male   |
+----+--------+------+--------+
5 rows in set (0.00 sec)

mysql> delete from info where age=30;
Query OK, 2 rows affected (0.00 sec)

mysql> select * from info;
+----+------+------+--------+
| id | NAME | age  | gender |
+----+------+------+--------+
|  2 | lili |   20 | female |
|  5 | java |   40 | male   |
|  6 | go   |   50 | male   |
+----+------+------+--------+
3 rows in set (0.00 sec)

改 - update

对表中已经存在的记录进行修改。

-- update 表名 set 字段1=值1, 字段2=值2 where 条件;
-- 如果不加where条件会将表中所有记录都修改
mysql> update info set name='xxx', age=100;
Query OK, 3 rows affected (0.00 sec)
Rows matched: 3  Changed: 3  Warnings: 0

mysql> select * from info;
+----+------+------+--------+
| id | NAME | age  | gender |
+----+------+------+--------+
|  2 | xxx  |  100 | female |
|  5 | xxx  |  100 | male   |
|  6 | xxx  |  100 | male   |
+----+------+------+--------+
3 rows in set (0.00 sec)

-- 如果不想修改全部的记录就需要使用where条件
mysql> update info set name='test', age=10 where id=2;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0

mysql> select * from info;
+----+------+------+--------+
| id | NAME | age  | gender |
+----+------+------+--------+
|  2 | test |   10 | female |
|  5 | xxx  |  100 | male   |
|  6 | xxx  |  100 | male   |
+----+------+------+--------+
3 rows in set (0.00 sec)

查 - select

表与表之间有时是有关系的,尤其是在同一个项目中的表,因此查询数据就分为单表查询和多表查询。这里师门使用MySQL官方提供的MySQL示例进行介绍查询操作,打开压缩包之后是world.sql文件,如何将这个文件导入到MySQL中呢,可以通过下面的语法:

-- source .sql文件的路径
mysql> source  C:\Users\12801\Desktop\world.sql

mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| book_manage        |
| mysql              |
| performance_schema |
| stu                |
| test               |
| world              |
+--------------------+
7 rows in set (0.00 sec)

单表查询

查询语句的标准用法是需要select配合其他子句进行查询,因为在实际项目开发中并不是每次都需要查询所有的数据,而是需要一些过滤条件进行过滤,查询出需要的数据,并且在实际开发中不推荐查询所有数据,因为如果一张表中数据太多的话,内存可能会不够用哦~会导致电脑卡死...

首先和select配合使用的子句有以下几个select /from/where/group by/having/order by/limit,上面这些子句的书写顺序也是默认的SQL书写顺序。

from子句

是从哪张表中查询数据。

-- select 列名 from 表名;

-- 全表扫描,查询country表中的所有数据,不建议这样操作,数据过多可能导致电脑卡死
mysql>select * from country;  

-- 只查询表中部分列的所有值,查询country表中的code、name列的所有值
mysql> select code, name from country;

where子句

where子句就需要和过滤条件配合使用,过滤条件包括= > < <= >= != and or not like in (between and),以下述例子进行说明:

-- 查询中国所有城市信息
select * from city where countrycode='CHN';

-- 中国人口大于1000000的城市信息
select * from city countrycode='CHN' and population>5000000; 

-- 查询省的名字前面带guang开头的,注意:like语句时,%不能放在前面,因为不走索引(索引会在后续文章中介绍,这里就简单理解索引就是书的目录)
select * from city where district like 'guang%';

-- 查询中国和美国所有城市信息
select * from city where countrycode in ('CHN' ,'USA');

-- 查询世界上人口数量大于100w小于200w的城市信息
select * from city where population >1000000 and population <2000000;

-- 查询世界上人口数量大于100w小于200w的城市信息
select * from city where population between 1000000 and 2000000;

group by子句

group by是分组查询,根据情况是否需要where过滤条件,group by一般需要配合聚合函数使用,group by大致逻辑是取出分组和聚合函数参数的数据,根据分组依据进行排序,排序后对分组依据进行去重,由于MySQL数据库中不允许一行数据与多行数据对应(only_full_group_by严格模式),因此需要使用聚合函数将多个数据整合为与分组依据对应的一个数据。

聚合函数有max() min() sum() avg()---平均数 count()---计数 group_concat()---列转行等。

-- 统计世界上每个国家的总人口数
select countrycode ,sum(population) from  city  group by countrycode;

-- 统计中国每个省的人口数
select district,sum(Population) from city  where countrycode='chn' group by district;

-- 统计中国每个省的名字,人数,城市个数,城市名字(由于严格模式,一行数据不能对应多行数据,需要使用group_concat聚合函数进行列转行操作)。
select district, sum(population), count(id), group_concat(name) from world.city where countrycode='chn' group by district;

having子句

having子句与where子句功能差不多,只不过having是对分组后的数据进行筛选。

-- 统计中国每个省的总人口数,只打印总人口数小于100
select district,sum(Population) from city where countrycode='chn'group by district having sum(Population) < 1000000 ;

order by

按照指定顺序输出结果,默认是从小到大,desc是从大到小。

-- 统计中国每个省的总人口数,只打印总人口数小于100,从大到小排列。
select district,sum(Population) from city where countrycode='chn'
group by district having sum(Population) < 1000000 order by sum(population) desc;

limit

将结果分页显示,通常配合order by使用

-- LIMIT N, M;  -- 跳过N行,显示M行
-- LIMIT M OFFSET N; -- 跳过N行,显示M行
select district,sum(Population) from city where countrycode='chn'group by district having sum(Population) < 1000000 order by sum(population) desc limit 5 6; -- 统计中国每个省的总人口数,只打印总人口数小于100,从大到小排列,只显示前6~11条。

多表查询

需要的数据来自于多张表,单表无法满足,实际上是将多张表有关联的数据合并成一张新表,在新表中做where group by等子句等操作。

多表连接查询类型大概有三种类型,分别是笛卡尔乘积、内连接和外连接。

笛卡尔乘积join

是将多张表的数据合并成大表,不推荐使用。

select * from teacher join course; 

内连接inner join

应用最广泛,取两张表有关联部分的数据,A表 inner join B表 on A.xx=B.xx;

-- teacher表和course表,查询teacher表中tno等于course表中的tno的数据
select * from teacher (inner) join course on(where) teacher.tno=course.tno;

外连接left join/right join

left join左表所有的数据都展示,右表只展示与左表有关联的数据,没有对应项的用null标识;right join右表所有的数据都展示,左表只展示与右表有关联的数据,没有对应项的用null标识。

作用就是强制驱动表,将小表(查询得到的结果更少的结果集)作为驱动表降低next loop(循环)次数。

select city.name, cpuntry.name, city.population from city left join country on city.countrycode=country.code and city.poplation<100;

驱动表的原理

join...on...的实现原理:拿到其中一张表作为驱动表,使用关联条件(on的条件)去和另一张表(内层循环)比对,如果符合就将这两张表的数据进行拼接。当两张表的行数差异较大时,将小表(查询得到的结果更少的结果集)作为驱动表,可以优化查询降低next loop的次数,对于内连接来说,无法控制驱动表是谁,完全由优化器决定,如果需要人为干预驱动表,可以通过外连接实现。

left join中驱动表就是左表,类似于双层for循环的外层循环,强制将左表作为驱动表.

结语

文章首发于微信公众号程序媛小庄,同步于掘金知乎

码字不易,转载请说明出处,走过路过的小伙伴们伸出可爱的小指头点个赞再走吧(╹▽╹)

wallhaven-ne9wxw_1920x1080.png