MySQL 小记 数据库操作 表操作 数据操作 条件 聚合 分组 排序 获取部分行 外键 连接查询 子查询 字符串函数 数学函数 日期时间函数 视图 事务

MySQL 小记
数据库操作
表操作
数据操作
条件
聚合
分组
排序
获取部分行
外键
连接查询
子查询
字符串函数
数学函数
日期时间函数
视图
事务

之前本人说过一款非关系型数据库的代表 Redis 的《 Redis 小记 》文章 和介于关系型数据库与非关系型数据库之间的《 MongoDB 小记 》文章,今天我们再来看一款关系型数据库 MySQL。

MySQL 数据库是应该是大家用的最多最广的数据库,我就不再多累赘了,直接开说了。

 MySQL 小记
数据库操作
表操作
数据操作
条件
聚合
分组
排序
获取部分行
外键
连接查询
子查询
字符串函数
数学函数
日期时间函数
视图
事务

如上图,在终端输入 

mysql -uroot -p

回车输入密码,没设置的跳过输入,出现如上的画面即表示我们已经连接 MySQL 成功。

创建数据库

create database 数据库名 charset=utf8;

删除数据库

drop database 数据库名;

切换数据库

use 数据库名;

查看当前选择的数据库

select database();

表操作

查看当前数据库中所有表

show tables;

创建表

auto_increment表示自动增长

create table 表名(列及类型);
如:
create table students(
id int auto_increment primary key,
sname varchar(10) not null
);

修改表

alter table 表名 add|change|drop 列名 类型;
如:
alter table students add birthday datetime;

删除表

drop table 表名;

查看表结构

desc 表名;

更改表名称

rename table 原表名 to 新表名;

查看表的创建语句

show create table '表名';

数据操作

查询

select * from 表名

增加

全列插入:insert into 表名 values(...)
缺省插入:insert into 表名(列1,...) values(值1,...)
同时插入多条数据:insert into 表名 values(...),(...)...;
或insert into 表名(列1,...) values(值1,...),(值1,...)...;

主键列是自动增长,但是在全列插入时需要占位,通常使用0,插入成功后以实际数据为准

修改

update 表名 set 列1=值1,... where 条件

删除

delete from 表名 where 条件

逻辑删除,本质就是修改操作update

alter table students add isdelete bit default 0;
如果需要删除则
update students isdelete=1 where ...;

以上为 MySQL 数据库的一些基本操作,本人就直接贴在上面了。

对于 MySQL 来说,操作起来也比较方便,本人就不做过多解释说明和代码演示,由于太懒了,所以直接就借鉴了别人的代码说明,写的特别好,直接贴下去了,已被自己需要时翻阅。

查询的基本语法

select * from 表名;
  • from关键字后面写表名,表示数据来源于是这张表

  • select后面写表中的列名,如果是*表示在结果中显示表中所有列

  • 在select后面的列名部分,可以使用as为列起别名,这个别名出现在结果集中

  • 如果要查询多个列,之间使用逗号分隔

消除重复行

在select后面列前使用distinct可以消除重复的行

select distinct gender from students;

条件

使用where子句对表中的数据筛选,结果为true的行会出现在结果集中

语法如下:

select * from 表名 where 条件;

比较运算符

  • 等于=

  • 大于>

  • 大于等于>=

  • 小于<

  • 小于等于<=

  • 不等于!=或<>

  • 查询编号大于3的学生

select * from students where id>3;

查询编号不大于4的科目

select * from subjects where id<=4;

查询姓名不是“黄蓉”的学生

select * from students where sname!='黄蓉';

查询没被删除的学生

select * from students where isdelete=0;

逻辑运算符

  • and

  • or

  • not

  • 查询编号大于3的女同学

select * from students where id>3 and gender=0;

查询编号小于4或没被删除的学生

select * from students where id<4 or isdelete=0;

模糊查询

  • like

  • %表示任意多个任意字符

  • _表示一个任意字符

  • 查询姓黄的学生

select * from students where sname like '黄%';

查询姓黄并且名字是一个字的学生

select * from students where sname like '黄_';

 查询姓黄或叫靖的学生

select * from students where sname like '黄%' or sname like '%靖%';

范围查询

  • in表示在一个非连续的范围内

  • 查询编号是1或3或8的学生

select * from students where id in(1,3,8);

between ... and ...表示在一个连续的范围内

查询学生是3至8的学生

select * from students where id between 3 and 8;

查询学生是3至8的男生

select * from students where id between 3 and 8 and gender=1;

空判断

  • 注意:null与''是不同的

  • 判空is null

  • 查询没有填写地址的学生

select * from students where hometown is null;

判非空is not null

查询填写了地址的学生

select * from students where hometown is not null;

查询填写了地址的女生

select * from students where hometown is not null and gender=0;

优先级

  • 小括号,not,比较运算符,逻辑运算符

  • and比or先运算,如果同时出现并希望先算or,需要结合()使用

聚合

  • 为了快速得到统计数据,提供了5个聚合函数

  • count(*)表示计算总行数,括号中写星与列名,结果是相同的

  • 查询学生总数

select count(*) from students;

max(列)表示求此列的最大值

查询女生的编号最大值

select max(id) from students where gender=0;

min(列)表示求此列的最小值

查询未删除的学生最小编号

select min(id) from students where isdelete=0;

sum(列)表示求此列的和

查询男生的编号之后

select sum(id) from students where gender=1;

avg(列)表示求此列的平均值

查询未删除女生的编号平均值

select avg(id) from students where isdelete=0 and gender=0;

分组

  • 按照字段分组,表示此字段相同的数据会被放到一个组中

  • 分组后,只能查询出相同的数据列,对于有差异的数据列无法出现在结果集中

  • 可以对分组后的数据进行统计,做聚合运算

  • 语法:

select 列1,列2,聚合... from 表名 group by 列1,列2,列3...

查询男女生总数

select gender as 性别,count(*)
from students
group by gender;

查询各城市人数

select hometown as 家乡,count(*)
from students
group by hometown;

分组后的数据筛选

语法:

select 列1,列2,聚合... from 表名
group by 列1,列2,列3...
having 列1,...聚合...

having后面的条件运算符与where的相同

查询男生总人数

方案一
select count(*)
from students
where gender=1;
-----------------------------------
方案二:
select gender as 性别,count(*)
from students
group by gender
having gender=1;

对比where与having

  • where是对from后面指定的表进行数据筛选,属于对原始数据的筛选

  • having是对group by的结果进行筛选

排序

  • 为了方便查看数据,可以对数据进行排序

  • 语法:

select * from 表名
order by 列1 asc|desc,列2 asc|desc,...
  • 将行数据按照列1进行排序,如果某些行列1的值相同时,则按照列2排序,以此类推

  • 默认按照列值从小到大排列

  • asc从小到大排列,即升序

  • desc从大到小排序,即降序

  • 查询未删除男生学生信息,按学号降序

select * from students
where gender=1 and isdelete=0
order by id desc;

查询未删除科目信息,按名称升序

select * from subject
where isdelete=0
order by stitle;

获取部分行

  • 当数据量过大时,在一页中查看数据是一件非常麻烦的事情

  • 语法

select * from 表名
limit start,count
  • 从start开始,获取count条数据

  • start索引从0开始

示例:分页

  • 已知:每页显示m条数据,当前显示第n页

  • 求总页数:此段逻辑后面会在python中实现

    • 查询总条数p1

    • 使用p1除以m得到p2

    • 如果整除则p2为总数页

    • 如果不整除则p2+1为总页数

  • 求第n页的数据

select * from students
where isdelete=0
limit (n-1)*m,m

外键

  • 思考:怎么保证关系列数据的有效性呢?任何整数都可以吗?

  • 答:必须是学生表中id列存在的数据,可以通过外键约束进行数据的有效性验证

  • 为stuid添加外键约束

alter table scores add constraint stu_sco foreign key(stuid) references students(id);

此时插入或者修改数据时,如果stuid的值在students表中不存在则会报错

在创建表时可以直接创建约束

create table scores(
id int primary key auto_increment,
stuid int,
subid int,
score decimal(5,2),
foreign key(stuid) references students(id),
foreign key(subid) references subjects(id)
);

外键的级联操作

  • 在删除students表的数据时,如果这个id值在scores中已经存在,则会抛异常

  • 推荐使用逻辑删除,还可以解决这个问题

  • 可以创建表时指定级联操作,也可以在创建表后再修改外键的级联操作

  • 语法

alter table scores add constraint stu_sco foreign key(stuid) references students(id) on delete cascade;
  • 级联操作的类型包括:

    • restrict(限制):默认值,抛异常

    • cascade(级联):如果主表的记录删掉,则从表中相关联的记录都将被删除

    • set null:将外键设置为空

    • no action:什么都不做 

连接查询

  • 连接查询分类如下:

    • 表A inner join 表B:表A与表B匹配的行会出现在结果中

    • 表A left join 表B:表A与表B匹配的行会出现在结果中,外加表A中独有的数据,未对应的数据使用null填充

    • 表A right join 表B:表A与表B匹配的行会出现在结果中,外加表B中独有的数据,未对应的数据使用null填充

  • 在查询或条件中推荐使用“表名.列名”的语法

  • 如果多个表中列名不重复可以省略“表名.”部分

  • 如果表的名称太长,可以在表名后面使用' as 简写名'或' 简写名',为表起个临时的简写名称

子查询

  • 查询支持嵌套使用

  • 查询各学生的语文、数学、英语的成绩

select sname,
(select sco.score from scores sco inner join subjects sub on sco.subid=sub.id where sub.stitle='语文' and stuid=stu.id) as 语文,
(select sco.score from  scores sco inner join subjects sub on sco.subid=sub.id where sub.stitle='数学' and stuid=stu.id) as 数学,
(select sco.score from  scores sco inner join subjects sub on sco.subid=sub.id where sub.stitle='英语' and stuid=stu.id) as 英语
from students stu;

字符串函数

查看字符的ascii码值ascii(str),str是空串时返回0

select ascii('a');

查看ascii码值对应的字符char(数字)

select char(97);

拼接字符串concat(str1,str2...)

select concat(12,34,'ab');

包含字符个数length(str)

select length('abc');
  • 截取字符串

    • left(str,len)返回字符串str的左端len个字符

    • right(str,len)返回字符串str的右端len个字符

    • substring(str,pos,len)返回字符串str的位置pos起len个字符

select substring('abc123',2,3);
  • 去除空格

    • ltrim(str)返回删除了左空格的字符串str

    • rtrim(str)返回删除了右空格的字符串str

    • trim([方向 remstr from str)返回从某侧删除remstr后的字符串str,方向词包括both、leading、trailing,表示两侧、左、右

select trim('  bar   ');
select trim(leading 'x' FROM 'xxxbarxxx');
select trim(both 'x' FROM 'xxxbarxxx');
select trim(trailing 'x' FROM 'xxxbarxxx');

返回由n个空格字符组成的一个字符串space(n)

select space(10);

替换字符串replace(str,from_str,to_str)

select replace('abc123','123','def');
  • 大小写转换,函数如下

    • lower(str)

    • upper(str)

select lower('aBcD');

数学函数

求绝对值abs(n)

select abs(-32);

求m除以n的余数mod(m,n),同运算符%

select mod(10,3);
select 10%3;

地板floor(n),表示不大于n的最大整数

select floor(2.3);

天花板ceiling(n),表示不小于n的最大整数

select ceiling(2.3);

求四舍五入值round(n,d),n表示原数,d表示小数位置,默认为0

select round(1.6);

求x的y次幂pow(x,y)

select pow(2,3);

获取圆周率PI()

select PI();

随机数rand(),值为0-1.0的浮点数

select rand();

还有其它很多三角函数,使用时可以查询文档

日期时间函数

  • 获取子值,语法如下

    • year(date)返回date的年份(范围在1000到9999)

    • month(date)返回date中的月份数值

    • day(date)返回date中的日期数值

    • hour(time)返回time的小时数(范围是0到23)

    • minute(time)返回time的分钟数(范围是0到59)

    • second(time)返回time的秒数(范围是0到59)

select year('2016-12-21');

日期计算,使用+-运算符,数字后面的关键字为year、month、day、hour、minute、second

select '2016-12-21'+interval 1 day;
  • 日期格式化date_format(date,format),format参数可用的值如下

    • 获取年%Y,返回4位的整数

      * 获取年%y,返回2位的整数

      * 获取月%m,值为1-12的整数

    • 获取日%d,返回整数

      * 获取时%H,值为0-23的整数

      * 获取时%h,值为1-12的整数

      * 获取分%i,值为0-59的整数

      * 获取秒%s,值为0-59的整数

select date_format('2016-12-21','%Y %m %d');

当前日期current_date()

select current_date();

当前时间current_time()

select current_time();

当前日期时间now()

select now();

视图

  • 对于复杂的查询,在多次使用后,维护是一件非常麻烦的事情

  • 解决:定义视图

  • 视图本质就是对查询的一个封装

  • 定义视图

create view stuscore as 
select students.*,scores.score from scores
inner join students on scores.stuid=students.id;

视图的用途就是查询

select * from stuscore;

事务

  • 当一个业务逻辑需要多个sql完成时,如果其中某条sql语句出错,则希望整个操作都退回

  • 使用事务可以完成退回的功能,保证业务逻辑的正确性

  • 事务四大特性(简称ACID)

    • 原子性(Atomicity):事务中的全部操作在数据库中是不可分割的,要么全部完成,要么均不执行

    • 一致性(Consistency):几个并行执行的事务,其执行结果必须与按某一顺序串行执行的结果相一致

    • 隔离性(Isolation):事务的执行不受其他事务的干扰,事务执行的中间结果对其他事务必须是透明的

    • 持久性(Durability):对于任意已提交事务,系统必须保证该事务对数据库的改变不被丢失,即使数据库出现故障

  • 要求:表的类型必须是innodb或bdb类型,才可以对此表使用事务

  • 查看表的创建语句

show create table students;

修改表的类型

alter table '表名' engine=innodb;

事务语句

开启begin;
提交commit;
回滚rollback;

示例1

步骤1:打开两个终端,连接mysql,使用同一个数据库,操作同一张表

终端1:
select * from students;
------------------------
终端2:
begin;
insert into students(sname) values('张飞');

步骤2

终端1:
select * from students;

步骤3

终端2:
commit;
------------------------
终端1:
select * from students;

示例2

步骤1:打开两个终端,连接mysql,使用同一个数据库,操作同一张表

终端1:
select * from students;
------------------------
终端2:
begin;
insert into students(sname) values('张飞');

步骤2

终端1:
select * from students;

步骤3

终端2:
rollback;
------------------------
终端1:
select * from students;

好记性不如烂笔头,特此记录,与君共勉!