一、数据库
1.数据库概述
数据库:存储数据的仓库,其本质是一个文件系统,数据按照特定的格式将数据存储起来,用户可以对数据库中的数据进行增加,修改,删除及查询操作
数据库管理系统(DataBase Management System):DBMS 一种操作和管理数据库的大型软件,用于建立、使用和维护数据库,对数据库进行统一管理和控制,以保证数据库的安全性和完整性
Java相关的数据库:MYSQL,Oracle
2.数据库表
数据库中以表为组织单位存储数据
表类似java类,每个字段都有对应的数据类型。
类--表,类中属性--字段,对象--记录
3.表数据
表中一行一行的信息称为记录
二、MySql数据库
1.MySql安装
2.登录MySql数据库
MySQL是一个需要账户名密码登录的数据库
mysql –u用户名 –p密码
mysql --host=ip地址 --user=用户名 --password=密码
3.MySQL真正的 utf8 是使用 utf8mb4
三、SQL语句
1.SQL语句
数据定义语言:简称DDL(Data Definition Language),用来定义数据库对象:数据库,表,列等。关键字:create,alter,drop等
数据操作语言:简称DML(Data Manipulation Language),用来对数据库中表的记录进行更新。关键字:insert,delete,update等
数据控制语言:简称DCL(Data Control Language),用来定义数据库的访问权限和安全级别,及创建用户。
数据查询语言:简称DQL(Data Query Language),用来查询数据库中表的记录。关键字:select,from,where等
2.SQL通用语法
sql语句可以单行或多行书写,以分号结尾
可使用空格和缩进来增强语句的可读性
sql语句不区分大小写,建议使用大写
使用/**/的方式完成注释
3.数据库操作
创建数据库 create database 数据库名 (character set 字符集);
查看所有数据库 show databases;
删除数据库 drop database 数据库名称;
切换数据库 use 数据库名;
查看正在使用的数据库 select database();
4.表结构相关语句
创建表 create table 表名(字段名 类型 约束);
查看表 show tables;
查看表结构 desc 表名;
删除表 drop table 表名;
修改表结构格式 alter table 表名 add 列名 类型(长度)约束;
新添字段在某个字段后 alter table 表名 add 列名 类型(长度) 约束 after 某个字段;
修改表修改列的类型长度及约束 alter table 表名 modify 列名 类型(长度) 约束
修改表修改列名 alter table 表名 change 旧列名 新列名 类型(长度) 约束;
修改表删除列 alter table 表名 drop 列名;
修改表名 rename table 表名 to 新表名;
修改表的字符集 alter table 表名 character set 字符集;
四、字段属性
1.主键
primary key,一张表只有一个字段可设置为主键,唯一不重复不能为NULL
主键使用整数类型
主键可以有多个字段组成联合主键
没有办法更新主键,主键必须先删除,才能增加
2.自动增长
自增长的字段必须定义为主键,默认起始值是1而不是0
自增长特点
任何一个字段要做自增长必须前提是本身是一个索引(key一栏有值),auto_increment表示自动编号
自增长字段必须是数字(整型)
一张表最多只能有一个自增长
自增长的使用
当自增长被给定的值为NULL或者默认值的时候会触发自动增长
自增长如果对应的字段输入了值,那么自增长失效,下次还能够正确的自增长(从最大值+1)
3.唯一键(unique key)
唯一键默认允许为空,而且是多个为空
一张表可以有多个唯一键
4.外键(foreign key)
一张表中有一个字段(非主键)指向另外一张表的主键,那么将该字段称为外键
一张表可以有多个外键
外键不可修改,只能先删除后增加
外键的作用
一个对父表,一个对子表(外键字段所在的表)
对子表约束:子表数据进行写操作(增和改)的时候,如果对应的外键字段在父表找不到对应的匹配,那么操作会失败
对父表约束:父表数据进行写操作(删和改,都必须涉及到主键本身),如果对应的主键在子表中已经被数据所引用,那么就不允许操作
外键条件
外键字段的字段类型(列类型)必须与父表的主键类型完全一致
一张表中的外键名字不能重复
增加外键的字段(数据已经存在),必须保证数据与父表主键要求对应
5.索引
系统根据某种算法,将已有的数据(未来可能新增的数据),单独建立一个文件,文件能够实现快速的匹配数据,并且能够快速的找到对应表中的记录
几乎所有的索引都建立在字段上
经常被用来做检索条件的字段需要加上索引,原理是B+树
如果是几千条数据,不必加索引,全表扫描也很快
创建索引 create table 表名称(...,INDEX [索引名称](字段名),...)
添加索引
普通索引
CREATE INDEX 索引名称 ON 表名(字段);
ALTER TABLE 表名 ADD INDEX 索引名称(字段);
唯一索引
CREATE UNIQUE INDEX 索引名称 ON 表名(字段);
联合索引
CREATE INDEX 索引名称 ON 表名(字段1,字段2...)
查询索引 SHOW INDEX FROM 表名;
删除索引 DROP INDEX 索引名称 ON 表名;
索引的使用原则
数据量很大,且经常被查询的数据表
索引只添加在经常被用作检索条件的字段上
不要在大字段上创建索引
索引的意义
提升查询数据的效率
约束数据的有效性(唯一性等)
增加索引的前提条件:索引本身会产生索引文件,会非常消耗磁盘空间
mysql中的索引
主键索引:primary key
唯一索引:unique key
全文索引:fulltext index 全文索引针对文章内部的关键字进行索引
普通索引:index
五、关系
表与表之间的关系:一对一、一对多(多对一)和多对多
1.一对一
一张表的一条记录只能与另外一张表的一条记录进行对应,反之亦然
2.一对多(多对一)
一张表(A)中有一条记录可以对应另外一张表(B)中的多条记录;另一张表(B)的一条记录只能对应第一张表(A)的一条记录
3.多对多
一张表(A)中有一条记录可以对应另外一张表(B)中的多条记录;同时表(B)中的一条记录也能对应表(A)中的多条记录
多对多情况一般是增加一张中间关系表,专门维护两个表之间的关系
六、范式
Normal Format是为了解决一种数据的存储与优化的问题
保存数据的存储之后,凡是能够通过关系寻找出来的数据,坚决不再重复存储
范式分为六层,每一层都比上一层严格。
数据库设计的时候一般只满足前三种范式的需求
范式在数据库设计当中有指导意义,但不是强制规范
第一范式(1NF):要求字段的数据具有原子性,不可再分
第二范式(2NF):数据表中的每条记录必须是唯一的,添加主键列
第三范式(3NF):每列都与主键有直接关系,不存在传递依赖
逆规范化是磁盘利用率与效率的对抗
七、数据高级操作
1.新增数据(insert)
Insert into 表名 [字段1,字段2,......] values (值1,值2,......); /*插入单条记录*/
Insert into 表名 [字段1,字段2,......] values (值1,值2,......), (值1,值2,......); /*插入多条记录*/
insert into 表名 set 字段1=值1,字段2=值2... 只有mysql数据库可用
IGNORE关键字:插入数据库不存在的记录
INSERT [IGNORE] into 表名 ...;
主键冲突
更新操作 insert into 表名 [字段列表:包含主键] values(值列表) on duplicate key update 字段=values(字段);
替换 replace into 表名 [(字段列表:包含主键)] values(值列表);
蠕虫复制
从已有的数据中去获取数据,然后将数据又进行新增操作,数据成倍的增加
insert into 表名[(字段列表)] select 字段列表/ * from 数据表名;
复制表结构 create table 表名 like 数据库.表名
2.更新数据(update)
表连接的update语句可以修改多张表的记录
update语句中的内连接
update 表1 join 表2 on 条件 set 字段1=值1,字段2=值2;
update 表1 join 表2 set 字段1=值1,字段2=值2 where 条件;
update语句中的外连接
update 表1 [left | right] join 表2 on 条件 set 字段1=值1,字段2=值2;
3.删除数据(delete)
DELETE [IGNORE] FROM 表名 [WHERE 条件1, 条件2, ...] [ORDER BY ...] [LIMIT ...];
delete语句中的内连接
delete 表1,表2 from 表1 join 表2 on 条件 [where 条件] [order by] [limit...];
delete语句中的外连接
delete 表1,表2 from 表1 [left | right] 表2 on 条件 [where 条件] [order by] [limit...];
快速删除数据表全部记录(速度快)
truncate table 表名;
注意:
1. drop(drop table 表名)是完全删除表,包括表结构,数据库就查不到这个表了
2. delete(delete from 表名)是删除表数据,保留表的结构,数据库中该表还存在,如果加where条件,可以只删除一行或者多行,下次插入id不会从1开始,而是从最后一次插入的id+1开始
3. truncate (truncate table 表名)只能删除全表数据,会保留表结构,数据库中该表还存在,下次插入id从1开始
4.查询数据
Select [字段别名] from 数据源 [where条件子句] [group by子句] [having子句] [order by子句] [limit 子句];
1.去重查询 distinct
select distinct 字段 from 表名;
注:
distinct关键字只能在select子句中使用一次
distinct关键字只能写在select子句的第一个字段前面,否则报错,若有多个字段,则只有多个字段的值都相同的情况才会被认为是重复记录,distinct才会生效
2.字段别名
字段名 [as] 别名;
查询语句的执行顺序是先词法分析与优化,读取SQL语句,然后FROM子句选择数据来源,最后SELECT子句选择输出内容
3.数据源
数据源分为多种:单表数据源,多表数据源,查询语句
单表数据源 select * from 表名;
多表数据源 select * from 表1,表2...;
子查询 数据的来源是一条查询语句 select * from (select 语句) as 表名;
4.where子句
where子句:用来判断数据,筛选数据
where子句返回结果:0或者1,0代表false,1代表true
判断条件:
比较运算符: >, <, >=, <= ,!= ,<>, =, like, between and, in/not in
逻辑运算符: &&(and), ||(or), !(not)
判断某个字段是NULL where comm IS NULL
判断某个字段不为空 where comm IS NOT NULL
注意事项
where子句中不允许出现聚合函数
where子句中,条件执行的顺序是从左到右的,应把索引条件或者筛选掉记录最多的条件写在最左侧
子句的执行顺序是FROM->WHERE->SELECT->ORDER BY->LIMIT,先选择数据来源,再进行条件筛选,根据筛选完的记录
选择输出内容,接着进行排序,最后选择显示的限定条件
5.聚合函数
Count(): 统计分组后的记录数: 每一组有多少记录
count(*)和count(数字)用于获得包含空值的记录数
count(列名)用于获得包含非空值的记录数
Max(): 统计每组中非空的最大值
Min(): 统计非空的最小值
Avg(): 统计平均值
Sum(): 统计和
LENGTH():统计字符个数
ROUND():四舍五入为整数
注:聚合函数永远不可能出现在where子句里,一定会报错
几乎所有的聚合函数都会忽略空值(null),除了count(数字)、count(*)
6.Group by子句
语法:group by 字段名
主要用来分组查询,通过一定的规则将一个数据集划分为若干个小的区域,然后针对每个小区域分别进行数据汇总处理
根据某个字段进行分组(相同的放一组,不同的分到不同的组)
逐级分组:数据库支持多列分组条件,执行的时候逐级分组
group_concat(字段):把分组查询中的某个字段拼接成一个字符串,数据之间用,分隔
with rollup:对分组结果集做回溯统计,判断分组语句是否有问题,回溯统计的时候会将分组字段置空
分组会自动排序,根据分组字段默认升序
注意事项:
查询语句中含有group by子句时,select子句中只可包含聚合函数或者group by子句的分组列
当非聚合字段与group by字段具有一对一关系的时候,select子句中写非聚合字段有意义
子句的执行顺序是FROM -> WHERE -> GROUP BY -> SELECT -> ORDER BY -> LIMIT
form选择数据来源,where选择条件,符合条件的记录留下来,然后经过group by分组,分完组根据select子句
里面聚合函数做计算,然后order by对结果集排序,最后交给limit挑选返回哪些分页的数据显示
mysql5.7中,select列表包含group by子句未指定的列,会用默认第一个值来选择这些列的值,不会报错
mysql8.0中,使用group by时必须显示指定所有在select列表中使用的非聚合列,否则会导致错误
7.having子句
having子句和where子句一样是进行条件判断的
having子句的出现主要是为了where子句不能使用聚合函数的问题
having子句必须依赖于group by子句而存在,group by执行完后立即执行having子句
having子句判断只能和具体数值判断大小,不能和字段以及聚合函数判断,比较要有数值
having子句特殊用法:如果按照数字1分组,mysql会按照select子句中的列进行分组,having子句也可正常使用
where子句是针对磁盘数据进行判断,进入到内存之后会进行分组操作,分组操作需要having来处理
having和where的区别:
分组统计的结果或者说统计函数都只有having能够使用
having能够使用字段别名,where不能,where是从磁盘取数据,名字只能是字段名,别名是在字段进入到内存后才会产生
8.order by子句
语法:order by 字段名[asc|desc]
根据某个字段进行升序或者降序排序,默认是升序
注意事项:
子句的执行顺序是FROM->SELECT->ORDER BY->LIMIT
先选择数据来源,再选择输出内容看,接着进行排序,最后选择显示的限定条件
9.limit子句
两种使用方式
只用来限制长度(数据量):limit 数据量;
限制起始位置,限制数量:limit 起始位置,长度;
10.select语句中各关键字的先后顺序
(1) from
(2) on
(3) join
(4) where (可以使用表的别名)
(5) group by(可以开始使用select中字段的别名(不是表的别名),后面的语句中都可以使用)
(6) having + 聚合函数
(7) select
(8) distinct
(9) order by
(10) limit
1~3是table部分——形成表
4~6是filter部分——过滤条件
7~10是show部分——展示
八、连接查询
1.内连接 inner join
SELECT ... FROM 表1 INNER JOIN 表2 ON 连接条件;
SELECT ... FROM 表1 INNER JOIN 表2 WHERE 连接条件;
SELECT ... FROM 表1, 表2 WHERE 连接条件;
内连接保留符合条件的记录,查询条件写在on子句和where子句中的效果是相同的。
连接查询时关联条件on后面可以用某个字段在某个取值范围 on 字段 between A and B
可把聚合后的查询结果当做一个表,设置好别名,再和别的表去关联查询
2.外连接 left/right join
外连接里,条件写在where子句中,不符合条件的记录会被过滤掉,而不是保留下来
3.子查询
查询是在某个查询结果之上进行的
相关子查询:
反复子查询,要查询多次,效率特别低下
子查询的分类
from子查询:子查询跟在from之后,子查询只会执行一次,查询效率高
where子查询:子查询出现在where条件中,属于相关子查询,查询多次,不推荐,效率低下
select子查询:子查询跟在select之后,属于相关子查询,不推荐,效率低下
单行子查询和多行子查询
单行子查询的结果集只有一条记录,多行子查询结果集有多行记录
多行子查询只能出现在where子句和from子句中
where子句中的多行子查询
where子句中,用in all any exists关键字来处理多行表达式结果集的条件判断
子查询的EXISTS关键字(不常用)
EXISTS关键字是把原来在子查询之外的条件判断,写到了子查询的里面
语法:select ... from 表名 where [not] exists (子查询)