SQL
关系型数据库:指这种数据库不光光可以用来存储数据,还可以存储数据与数据之间的关系。一般是放在磁盘中的
非关系型数据库:非关系型数据库仅仅用来存储数据。非关系型数据库又有一个名字,叫NoSQL。存放在内存上,读写速度快
库
字符集:其实就是一套符号和编码。utf8,gbk,Latin1(不支持中文),utf8mb4(对UTF8的一个拓展),在创建的时候如果不指定字符集,默认是使用Latin1
校对规则:其实就是一套用来比较字符集内字符大小的规则。utf8_bin(区分大小写),utf8_general_ci(不区分大小写)
增
create database dbName character set utf8 collate utf8_bin;
删
drop database [if exists] dbName;
改
-- 修改库的名字(不支持) -- 修改库的字符集 alter database 36th character set gbk collate gbk_bin;
查
-- 查询库 -- 查询所有的库 show databases; -- 查询库的建库语句 可以帮助我们查看库的字符集和校对规则 show create database 36th;
表
常用的类型
整型:常用int,数据过大使用bigint
浮点型:float(4,2),double(6,2),decimal(8,2),前面的参数表示总共的位数,后面的表示小数位数,如果小数位数大于该参数,会自动四舍五入
date类型:year, date,time,datetime, timestamp
-- datetime 和timestamp的区别 -- 1. datetime 占用8个字节 timestamp占用4个字节 -- 2. timestamp默认时间是当前时间,datetime默认是null -- 3. timestamp 跟着mysql的时间走,而datetime跟着系统的时间走
使用now()可以获得当前时间,前面加上year等参数可以获取当前的年月日
year(now())
字符串类型:常用char、varchar(可变)、text(长文本)
枚举类型:只能选择其中的一个
enum('first','second','third')
集合类型:可以选择多个
set("bob","tom","jerry")
增
use database; create table user( name varchar(20), age int, gender enum('male','female') )character set utf8 collate utf8_bin;
删
drop table [if exists] user;
改
--改表名 rename table user to user1; --改表的字符集 alter table user character set utf8 collate utf8_bin; --修改列 --增加列 alter table user add height int; --删除列 alter table user drop height; --修改列的名字 alter table user change height width double(4,2); --修改列的类型 alter table user modify width int;
查
--查建表语句 show create table user; --查所有的表 show tables; --查表的结构 describe tableName; desc tableName;
数据
增
使用values关键字即可,如果没有指定插入列的话,插入的值需要与表的顺序一一对应
insert into user1 values (3,"云天明2号","男",'2000-10-19','2015-10-11','讲师',10000.00,'王道最可爱的天明妈妈'), (2,"长风","男",'2000-10-19','2015-10-11','讲师',20000.00,'王道最会单手打方向盘的男人');
插入的多个值使用逗号隔开
-- 插入指定列的值 insert into user1 (uid,name) values (1002,'楚云飞');
删
-- 删除 delete from user1; -- 删除指定的数据 where -- where是对表中的记录去过滤,筛选出符合条件的行(记录) delete from user1 where uid = 1; delete from user1 where name = '楚云飞'; -- 修改 -- 修改单列 update user1 set name = '短风';
改
-- 修改单列 update user1 set name = '长风' where uid = 1; -- 修改多列 update user1 set job = '总经理',resume='最大方的总经理' where uid = 1;
查
select关键字的额外功能:
now()获取当前时间
trim 消除空格
concat 拼接字符串
-- 查询 -- 查询表 t_students 中学生的姓名 select name from t_students; -- 查询多列 select id,name,class from t_students; --查询所有信息 select * from students;
关键字
where
用于过滤表中的数据,后面需跟一个布尔表达式
多个条件中间使用and或者or来连接
is null | is not null
is null :判断是否为空
is not null:判断是否不为空
但要注意,null和空字符串是有区别的
between and | not between and
between and 表示查询一个范围区间(闭区间)的成员
select * from students where math between 80 and 90;
in | not in
查询在一个指定范围内的成员
select * from students where class in ('36期','35期');
like | not like
模糊查询
-- like -- 模糊查询 -- % 表示通配 -- _表示占位 select * from students where name like '黄%'; select * from students where name like '黄_'; select * from students where name like '%黄%';
distinct
用于去重的关键字
-- 查询 students 表中的不同班级名 select distinct(class) from students;
需要注意的是,只有两行数据完全一致的时候才会去重,假如不一致,就不会去重
select distinct(class),name from students;
limit
限制结果集,可以控制语句输出的条数
-- 查询 students 表中第3到第5条记录; select * from students limit 2,3; --从下标为2的位置开始打印3个数据 --查询前3条记录 select * from students limit 3;
分页公式:
limit (page_no - 1) * page_size,page_size
order
排序
- 升序:默认值,ASC
- 降序:DESC
select * from students order by chinese desc,math asc,limit 3; -- 查询总成绩前三名同学的信息。 select * from students order by (chinese+math+english) desc limit 3;
计算字段
对一行中的数据进行计算
-- 查询总成绩信息 select name,chinese+english+math from students;
AS
对表或者列起别名
select * from (select name as '名字',chinese+math+english as"总分" from students) as user;
group by
对查询的结果进行分组
group_concat:对同一组的列的数组进行合并
select class,group_concat(id),group_concat(name) from students group by class;
having:对分组之后的结果进行过滤。分组后只能用having不能用where
-- 对于分组之后的结果过滤,我们要使用having关键字 -- 对于分组之前的原始表中的数据进行过滤,我们要使用where关键字 select class,count(*) as count from students group by class having count > 2;
count:统计分组的列数
聚合函数
- max
求最大值
select class,max(score) from student group by class;
- min
求最小值
select class,min(score) from student group by class;
- sum
求和
select class,sum(score) from student GROUP BY class;
- count
计数
select count(*) from student group by class;
- avg
select class,avg(score) from students group by class;
SQL语句的执行顺序
(5) SELECT column_name, ... (1) FROM table_name, ... (2) [WHERE ...] (3) [GROUP BY ...] (4) [HAVING ...] (6) [ORDER BY ...] (7) [limit...];
SQL的语句的原则:首先要输入你想要查询的数据,然后写明从哪个表查询,然后过滤原表数据,分组,分组之后的数据过滤,排序,limit永远在最后
数据完整性
数据完整性是为了保证插入到数据库中的数据是正确的,它防止了用户可能的输入错误。
实体完整性
主键:保证表中的每一条数据都是唯一的
- 主键是不重复的,唯一的
- 每一个表中必须得有一个主键
- 主键通常使用id来作为这个主键字段
- 主键不能为空
在MySQL中,我们的每一个表都有一个主键,如果用户没有设置的话,会自动生成一个隐藏的列作为主键
使用 auto_increment 关键字可以让主键自增,默认有一个记录,从1开始自增,会记录行数,如果前面的数据全部删除,会从原来自增到的地方往下自增
-- primary key 表示这个字段是主键 -- auto_increment 表示主键自增 create table t_user ( id int PRIMARY KEY auto_increment, name varchar(20) )character set utf8;
域完整性
表中的每一列都有一个特定的数据类型约束
- not null (不为空)
- unique (唯一)
create table t_user( id int PRIMARY KEY auto_increment, name varchar(20) not null, age int unique )character set utf8;
unique与主键的区别
- 主键不能为空,unique可以为空
- 存储方式有区别
参照完整性
外键:与其他表的数据相关联
create table province( id int PRIMARY KEY, name varchar(20) not null )character set utf8; create table city( id int PRIMARY KEY, name varchar(20) not null, province_id int, constraint fk_province_id foreign key(province_id) references province(id) )character set uft8;
建立外键后存在两个约束:
- 当我们添加或者修改城市表中的数据时,需要检测省份id是否存在于省份表中
- 当我们删除或者修改省份表时,要注意城市表中是否存在对应的省份id
- 注意主键不能作为外键,并且外键的字段长度要一致
多表设计
一对一
记录一一对应
- 人和身份证号
- 学生和学号
一对多
如果A(一)和B(多)两个表的关系是一对多的, 那么表中的数据应该有如下关系:
A表中的一条记录对应B表中的多条记录,B表中的一条记录对应A表的一条记录
关系数据应该记录在B表
常见的一对多模型:
- 省份和城市
- 班级和学生
- 院和系
- 分类和商品
多对多
多对多其实就是互为一对多,A表中的一条记录对应B表中的多条记录,B表中的一条记录对应A表中的多条记录
常见的多对多模型:
- 学生和课程
- 商品和订单
- 导师和学生
维护多对多的模型需要建立一个中间表
三大范式
第一范式
原子性:每一列存储的数据都是不可分割的,例如收货地址需要分割成省市区来存储
第二范式
**唯一性:**记录要有唯一的标识,不能有部分依赖
第三范式
字段不要冗余
在有些时候字段冗余可以降低维护的成本,所以在设计的时候如果一个表的查询需求远大于增删改的需求,那么可以适当的冗余,这种叫反范式化设计;在设计表的时候会遵循第一和第二范式,但第三范式看情况
多表查询
交叉连接
求两个表的笛卡尔积
select * from province cross join city;
内连接
在交叉连接的基础上进行筛选
- 显式内连接
select * from province inner join city on province.id = city.province_id;
- 隐式内连接
select * from province,city where province.id = city.province_id;
外链接
在交叉连接的基础上进行筛选,然后再做并集
- 左外连接
select * from province left outer join city on province.id = city.province_id;
- 右外连接
select * from province right outer join city on province.id = city.province_id;
- 三张表的连接查询
-- 内连接 select s.id as '学生id', s.name as '学生姓名', c.teacher_name as '老师名字', c.name as '课程名字' from student as s, sc, course as c where s.id = sc.sid and sc.cid = c.id; -- 外连接 select s.id as '学生id', s.name as '学生姓名', c.teacher_name as '老师名字', c.name as '课程名字' from student as s left join sc on s.id = sc.sid left join course as c on sc.cid = c.id;
子查询
可以嵌套的查询
-- 查询江苏省和湖北省的所有城市 select * from city where province_id in (select id from province where name = '江苏省' or name = '湖北省');
联合查询
联合查询可以合并查询的结果,并且去掉重复行
-- 联合查询 -- 双方的字段必须一致 select * from province where name = '湖北省' union select * from province where name = '安徽省';
数据的备份与恢复
- 备份
-- 1.打开cmd执行窗口 -- 2.执行命令 mysqldump -uroot -p dbname>文件全路径名
备份完成之后会生成一个sql文件,这个sql文件是这个数据库里面所有的表的建表语句以及数据信息。但备份的时候没有建库语句
- 恢复
-- 1.连接MySQL服务 mysql -uroot -p -- 2.建库 create database dbName; use dbname; -- 3.恢复 source src
枚举类型
public enum OrderStatus { // 枚举类型不可以创建实例对象 // 定义好枚举类型的实例对象 NOT_PAYED(1,"未支付"), PAYED(2,"已支付"), CANCEL(3,"取消") ; int id; String desc; OrderStatus(int id, String desc) { this.id = id; this.desc = desc; } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getDesc() { return desc; } public void setDesc(String desc) { this.desc = desc; } }