Mysql基础总结

714 阅读14分钟

本文为作者(石岩)原创,转载请指明出处:
juejin.cn/post/684490…

Mysql下载地址

dev.mysql.com/downloads/i…

Navicat Premium(破解免安装版)

pan.baidu.com/s/1WdOAmFpB…

Mysql表的数据类型

整数int

小数decimal

字符串varchar

日期datetime

约束

主键(primary key):代表一条记录的唯一标识,此自动记录的值必须唯一不能重复,不能为空。

非空(not null):此字段不允许填写空值。

唯一(unique):此字段的值不允许重复。

默认值(default):当不填写此值时会使用默认值,如果填写时以填写为主。

外键(foreign key):维护两个表之间的关联关系。

SQL语句

创建表

语法

create table 表名(  
字段名 数据类型 约束,  
字段名 数据类型 约束,  
...  
) 

案例:创建一张学生表,有姓名和年龄2个字段,姓名不能为空,最大长度不能超过10。

create table students(
    name varchar(10) not null,
    age int
)

案例:创建学生表,字段要求如下,姓名(长度为10),年龄,身高(保留小数点2位),需要创建自动增长主键。

create table students2(
id int unsigned primary key auto_increment,
name varchar(10),
age tinyint unsigned,
height decimal(5,2)
)

删除表

drop table if exists 表名

简单查询

select * from 表名

select 列名,列名,... from 表名

select 列名,列名,... from 表名 where 列名 = 值

插入语句

insert into 表名 values(...)

insert into 表名(列名1,...) values(值1,...)

修改语句

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

案例:修改表students的id为5的学生的数据,姓名改为狄仁杰,年龄改为20.

update students set name='狄仁杰',age=20 where id=5  

delete语句

语法 delete from 表名 where 列名称=值

案例:删除id为6的学生的数据

delete from students where id=6

案例:删除学生表所有数据
delete * from students

消除重复数据

select distinct 列名1,列名2,... from 表名

模糊查询(like)

案例:查询姓孙的学生

select * from students where name like '孙%'

案例:查询查询姓孙且名字是一个字的学生

select * from students where name like '孙_'

范围查询

案例:查询家乡是北京或上海或广东的学生

select * from students where hometown in('北京','上海','广东')

案例:查询年龄为18至20的学生

select * from students where age between 18 and 20

排序

案例:查询所有学生信息,按年龄从小到大排序

select * from students order by age asc

案例:查询所有学生信息,按年龄从大到小排序,年龄相同时,再按学号从小到大排序

select * from students order by age desc,studentNo

分组操作

案例:查询男生总人数

select sex,count(x) from students group by sex having sex='男'

分页查询

案例:已知:每页显示m条数据,求:显示第n页的数据

select * from students limit (n-1)*m,m

数据库设计

一对一关系
实体A对实体B为1对1,则在表A或表B中创建一个字段,存储另一个表的主键值

一对多关系
实体A对实体B为1对多:在表B中创建一个字段,存储表A的主键值

多对多关系 实体A对实体B为多对多:新建一张表C,这个表只有两个字段,一个用于存储A的主键值,一个用于存储B的主键值

等值连接

方式一
select * from 表1,表2 where 表1.列=表2.列

方式二(内连接)
select * from 表1 inner join 表2 on 表1.列=表2.列

准备数据

创建学生表
drop table if exists students;
create table students (
  studentNo varchar(10) primary key,
  name varchar(10),
  sex varchar(1),
  hometown varchar(20),
  age tinyint(4),
  class varchar(10),
  card varchar(20)
);
insert into students values
('001', '王昭君', '女', '北京', '20', '1班', '340322199001247654'),
('002', '诸葛亮', '男', '上海', '18', '2班', '340322199002242354'),
('003', '张飞', '男', '南京', '24', '3班', '340322199003247654'),
('004', '白起', '男', '安徽', '22', '4班', '340322199005247654'),
('005', '大乔', '女', '天津', '19', '3班', '340322199004247654'),
('006', '孙尚香', '女', '河北', '18', '1班', '340322199006247654'),
('007', '百里玄策', '男', '山西', '20', '2班', '340322199007247654'),
('008', '小乔', '女', '河南', '15', '3班', null),
('009', '百里守约', '男', '湖南', '21', '1班', ''),
('010', '妲己', '女', '广东', '26', '2班', '340322199607247654'),
('011', '李白', '男', '北京', '30', '4班', '340322199005267754'),
('012', '孙膑', '男', '新疆', '26', '3班', '340322199000297655')
创建课程表
drop table if exists courses;
create table courses (
  courseNo int(10) unsigned primary key auto_increment,
  name varchar(10)
);

insert into courses values 
('1', '数据库'),
('2', 'qtp'),
('3', 'linux'),
('4', '系统测试'),
('5', '单元测试'),
('6', '测试过程');
创建成绩表
drop table if exists scores;
create table scores (
  id int(10) unsigned primary key auto_increment,
  courseNo int(10),
  studentno varchar(10),
  score tinyint(4)
);

insert into scores values 
('1', '1', '001', '90'),
('2', '1', '002', '75'),
('3', '2', '002', '98'),
('4', '3', '001', '86'),
('5', '3', '003', '80'),
('6', '4', '004', '79'),
('7', '5', '005', '96'),
('8', '6', '006', '80');

案例:查询学生信息及学生的成绩
第一种

select * from students stu,scores sc where stu.studentNo=sc.studentNo

第二种(推荐)

select * from students stu inner join scores sc on stu.studentNo=sc.studentNo

案例:查询课程信息及课程的成绩
第一种
select * from courses co,scores sc where co.courseNo=sc.courseNo;

第二种(推荐)
select * from courses co inner join scores sc on co.courseNo = sc.courseNo;

案例:查询学生信息及学生的课程对应的成绩
第一种
select * from students st,courses co,scores sc where st.studentNo=sc.studentno and sc.courseNo=co.courseNo;

第二种(推荐)
select * from students st inner join scores sc on st.studentNo=sc.studentno inner join courses co on sc.courseNo=co.courseNo;

案例:查询王昭君的成绩,要求显示姓名、课程号、成绩
第一种
select st.name,sc.courseNo,sc.score from students st,scores sc where st.studentNo=sc.studentno and st.name='王昭君';

第二种(推荐)
select st.name,sc.courseNo,sc.score from students st inner join scores sc on st.studentNo=sc.studentno where st.name='王昭君';

案例:查询所有学生的数据库成绩,要求显示姓名、课程名、成绩
第一种

select st.name,co.name,sc.score from students st,scores sc,courses co where st.studentNo=sc.studentno and co.courseNo=sc.courseNo and co.name='数据库';

第二种(推荐)

select st.name,co.name,sc.score from students st inner join scores sc on st.studentNo=sc.studentno
inner join courses co on co.courseNo=sc.courseNo where co.name='数据库';

案例:查询男生中最高成绩,要求显示姓名、课程名、成绩
第一种

select st.name,co.name,sc.score from students st,scores sc,courses co where st.studentNo=sc.studentno and 
co.courseNo=sc.courseNo and st.sex='男' order by sc.score desc LIMIT 1;

第二种(推荐)

select st.name,co.name,sc.score from students st inner join scores sc on st.studentNo=sc.studentno inner join courses co on co.courseNo=sc.courseNo where st.sex='男' order by sc.score desc limit 1;

左连接

语法

select * from 表1
left join 表2 on 表1.列名=表2.列名;

案例:查询所有学生的成绩,包括没有成绩的学生

select st.name,sc.score from students st
left join scores sc on st.studentNo=sc.studentno;

案例:查询所有学生的成绩,包括没有成绩的学生,需要显示课程名

select st.name,sc.score,co.name from students st
left join scores sc on st.studentNo=sc.studentno
left join courses co on sc.courseNo=co.courseNo;

右连接

语法

select * from 表1
right join 表2 on 表1.列名=表2.列名;

案例:查询所有课程的成绩,包括没有成绩的课程

select * from scores sc
right join courses co on co.courseNo=sc.courseNo;

案例:查询所有课程的成绩,包括没有成绩的课程,包括学生

select * from scores sc
right join courses co on sc.courseNo=co.courseNo
left join students st on st.studentNo=sc.studentno;

自关联

准备数据

create table areas(
aid int primary key,
atitle varchar(20),
pid int
);

insert into areas 
values ('130000', '河北省', NULL),
('130100', '石家庄市', '130000'),
('130400', '邯郸市', '130000'),
('130600', '保定市', '130000'),
('130700', '张家口市', '130000'),
('130800', '承德市', '130000'),
('410000', '河南省', NULL),
('410100', '郑州市', '410000'),
('410300', '洛阳市', '410000'),
('410500', '安阳市', '410000'),
('410700', '新乡市', '410000'),
('410800', '焦作市', '410000');

案例:查询一共有多少个省

select count(*) from areas where areas.pid is null;

案例:查询河南省的所有城市
第一种

select * from areas p1,areas p2 where p1.aid=p2.pid and p1.atitle='河南省';

第二种(推荐)

select * from areas p1
inner join areas p2 on p1.aid=p2.pid
where p1.atitle='河南省';

案例:查询郑州市的所有区县
第一种

select * from areas a1,areas a2 where a1.aid=a2.pid and a1.atitle='郑州市';

第二种(推荐)

select * from areas ca 
inner join areas qa on ca.aid=qa.pid 
where ca.atitle='郑州市';

案例:查询河南省的所有区县

select * from areas p
left join areas c on c.pid=p.aid
left join areas a on a.pid=c.aid
where p.atitle='河南省';

子查询

标量子查询

定义:子查询返回的结果是一个数据(一行一列)
案例:查询大于平均年龄的学生

select * from students where age > (select avg(age) from students);

案例:查询王昭君的成绩,要求显示成绩

select * from scores where studentno=(select studentno from students where name='王昭君');
列子查询

定义:返回的结果是一列(一列多行)
案例:查询18岁的学生的成绩,要求显示成绩

select * from scores where studentNo in(select studentNo from students where age=18);
行级子查询

定义:返回的结果是一行(一行多列)
案例:查询男生中年龄最大的学生信息

select * from students where (sex,age)=(select sex,age from students where sex='男' order by age desc limit 1);
表级子查询

定义:返回的结果是多行多列
案例:查询数据库和系统测试的课程成绩
第一种

select * from scores sc
inner join courses co on sc.courseNo=co.courseNo
where co.name in('数据库','系统测试');

第二种(优化方案)

select * from scores sc 
inner join (select * from courses co where co.name in('数据库','系统测试')) c on sc.courseNo=c.courseNo;

命令行操作

登录 mysql -u 用户名 -p

显示所有数据库
show databases;

使用数据库
use 数据库名;

显示数据库中的所有表
show tables;

显示当前所在的数据库
select database();

创建数据库
create database 数据库名 charset='utf8';

删除数据库
drop database 数据库名;

备份数据库
mysqldump -u 用户名 -p 数据库名称 > 存储地址;

恢复数据库
mysql -u 用户名 -p 数据库名称 < 备份文件地址;

查看表结构
desc 表名;

查看创建表语句
show create table 表名;

自定义函数

语法

create function 函数名称(参数列表) returns 返回类型
begin
sql语句
end

案例:创建函数my_trim,用于删除字符串左右两侧的空格

create function my_trim(str varchar(100)) returns varchar(100)
begin
return ltrim(rtrim(str));
end

存储过程

语法

create procedure 存储过程名称(参数列表)
begin
sql语句
en

案例:创建查询过程,查询学生信息

create procedure proc_stu()
begin
select * from students;
end

call proc_stu();

注意事项

  • 存储过程和函数都是为了可重复的执行操作数据库的 sql 语句的集合.
  • 存储过程和函数都是一次编译,就会被缓存起来,下次使用就直接命中缓存中已经编译好的 sql, 不需要重复编译
  • 减少网络交互,减少网络访问流量

视图

  • 对于复杂的查询,在多个地方被使用,如果需求发生了改变,需要更改sql语句,则需要在多个地方进行修改,维护起来非常麻烦
  • 解决:定义视图
  • 视图本质就是对查询的封装
  • 定义视图,建议以v_开头
    语法
create view 视图名称 as select语句;

案例:创建视图,查询学生对应的成绩信息

create view v_stu_score_course as 
select
    stu.*,cs.courseNo,cs.name courseName,sc.score
from
    students stu
inner join scores sc on stu.studentNo = sc.studentNo
inner join courses cs on cs.courseNo = sc.courseNo

查看视图:查看表会将所有的视图也列出来

show tables;

删除视图

drop view 视图名称;

使用:视图的用途就是查询

select * from v_stu_score_course;

索引

  • 思考:在图书馆中是如何找到一本书的?
  • 一般的应用系统对比数据库的读写比例在10:1左右,而且插入操作和更新操作很少出现性能问题,遇到最多的,也是最容易出问题的,还是一些复杂的查询操作,所以查询语句的优化显然是重中之重
  • 当数据库中数据量很大时,查找数据会变得很慢
  • 优化方案:索引
创建索引

方式一:建表时创建索引

create table create_index(
id int primary key,
name varchar(10) unique,
age int,
key (age)
);

方式二:对于已经存在的表,添加索引

如果指定字段是字符串,需要指定长度,建议长度与定义字段时的长度一致
字段类型如果不是字符串,可以不填写长度部分

create index 索引名称 on 表名(字段名称(长度))
例:
create index age_index on create_index(age);
create index name_index on create_index(name(10));
查看索引
show index from 表名;
删除索引
drop index 索引名称 on 表名;
案例

1.创建测试表testindex

create table test_index(title varchar(10));

2.向表中加入十万条数据

//创建存储过程
create procedure proc_test()
begin
declare i int default 0;
while i<100000 do
insert into test_index(title) values(concat('test',i));
set i=i+1;
end while;
end 
//执行存储过程
call proc_test();

3.为表title_index的title列创建索引

create index title_index on test_index(title(10));

4.explain分析查询语句效率

explain
select * from test_index where title='test10000';

索引缺点
  • 虽然索引大大提高了查询速度,同时却会降低更新表的速度,如对表进行INSERT、UPDATE和DELETE,因为更新表时,MySQL不仅要保存数据,还要保存一下索引文件
  • 但是,在互联网应用中,查询的语句远远大于增删改的语句,甚至可以占到80%~90%,所以也不要太在意,只是在大数据导入时,可以先删除索引,再批量插入数据,最后再添加索引

外键foreign key

  • 如果一个实体的某个字段指向另一个实体的主键,就称为外键。被指向的实体,称之为主实体(主表),也叫父实体(父表)。负责指向的实体,称之为从实体(从表),也叫子实体(子表)
  • 对关系字段进行约束,当为从表中的关系字段填写值时,会到关联的主表中查询此值是否存在,如果存在则填写成功,如果不存在则填写失败并报错
创建外键

方式一:创建数据表的时候设置外键约束

create table goods_fk(
    id int unsigned primary key auto_increment,
    name varchar(150),
    cate_id int unsigned,
    brand_id int unsigned,
    price decimal(10,3) default 0,
    is_show bit default 1,
    is_saleoff bit default 0,
    foreign key(cate_id) references goods_cates(cate_id),
    foreign key(brand_id) references goods_brands(brand_id)
);

foreign key(自己的字段) references 主表(主表字段)

方式二:对于已经存在的数据表设置外键约束

-- 需要先获取外键约束名称
show create table goods;
-- 获取名称之后就可以根据名称来删除外键约束
alter table goods drop foreign key 外键名称;

alter table goods drop foreign key goods_ibfk_1;
alter table goods drop foreign key goods_ibfk_2;

修改密码

使用root登录,修改mysql数据库的user表

  • 使用password()函数进行密码加密
  • 注意修改完成后需要刷新权限
use mysql;

update user set authentication_string=password('新密码') where user='用户名';

例:
update user set authentication_string=password('123') where user='root';

刷新权限:flush privileges;

忘记 root 账户密码怎么办

1、配置mysql登录时不需要密码,修改配置文件

  • Centos中:配置文件位置为/data/server/mysql/my.cnf
  • Windows中:配置文件位置为C:\Program Files (x86)\MySQL\MySQL Server 5.1\my.ini 修改,找到mysqld,在它的下一行,添加skip-grant-tables
[mysqld]
skip-grant-tables

2、重启mysql,免密码登录,修改mysql数据库的user表

use mysql;

update user set authentication_string=password('新密码') where user='用户名';

例:
update user set authentication_string=password('123') where user='root';

刷新权限:flush privileges;

3、还原配置文件,把刚才添加的skip-grant-tables删除,重启

Mysql操作日志

general-log:能记录mysql所有的操作日志(包括增删改查),不过他会耗费数据库5%-10%的性能,所以一般没特别需要时不打开此功能,一般在查找问题时才打开,完成后及时关闭

1、客户端连接mysql
2、查询日志是否开启:show variables like 'general%';
3、打开日志:set global general_log=1
4、不需要使用日志时关闭日志:set global general_log=0
5、打开对应目录下的日志文件,操作mysql后,观察文件变化
    centos中查看文件自动刷新:tail -f 文件名