一,MySQL基本信息
1,MySQL底层逻辑
就是用户端,我们电脑连接DBMS系统,使用DBMS操作底层的数据库,而底层可以有,多个 数据库数据库内部又有多张表,表内记录的就是我们需要的数据
2,SQL基本语法
一 )SQL通用语法
1)SQL语法可以编写多行 ,以分号未结束字符
2)SQL可以使用空格或者缩进 增强阅读性
3)SQL语句不区分大小写,单关键字最好使用大写表示关键
注释:
单行注释:--注释单行内容 或 #注释 内容
多行注释:/*注释内容*/
二)SQL分类
DDL,DML,DQL,DCL
1)DDL语句
一)DDL-数据库操作
查询--查询所有数据库---SHOW DATABASES;
查询当前的数据库---SELECT DATABASES
创建--CREATE DATABASE[IF NOT EXISTS]数据库名字[DEFAULT CHASRSET 字符集][COLLATE 排序规则];
细节:[IF NOT EXISTS]是当数据库不存在时,就直接创建,但是假如数据库不存在,不会报错
[DEFAULT CHASRSET 字符集]设置字符类型,比如使用utf8,但是不建议使用utf8,因为数据库底层有一些特殊字符是四个字节,而utf8最多 只有三个字节,所以使用utf8mb4,就有四个字节
删除--DROP DATABASE[IF EXISTS]数据库名字
细节:[IF EXISTS]只有数据库存在才会执行删除操作,而不存在不会报错
使用--USE 数据库名
二)DDL-表查询
查询当前的数据库的所有表--show tables;(前提是先使用这个数据库)
查询表结构--desc 表名;
查询指定表的建表语句--show create table 表名;
三)DDL-表的创建
create table表名(
字段1 字段1类型[comment 字段1注释],
字段2 字段2类型[comment 字段2注释],
字段3 字段3类型[comment 字段3注释],
.........
字段n 字段n类型[comment 字段n注释]
)[comment 表注释];
四)DDL的数据类型
可分为三个部分:数值类型,字符串类型,日期时间类型
1)数值类型
tinyInt:1个字节 smallInt:2个字节 mediumInt:3个字节 int:4个字节
bigInt:8个字节 float:4个字节 double:8个字节
decimal:依赖设置的精度,标度(示例:123.45 --> 精度是5,标度是小数点后几位,就是2)
可以在类型后面加一个标识UNSIGNED这样就没有负数数据的范围
例如:age tinyInt UNSIGNED
分数表示:score double(4,1) - 表示数据长度是4,然后只有小数点的后一位
2)字符串类型
char类型是定长字符串,假设没有填满char类型,就会以空格来填补
varchar类型是可变字符串,会 根据输入的数据设置长度
二者相比,char的性能比较好,因为不需要计算用户填入的字符串长度
使用示例:填写用户名,使用 varchar(50) 因为用户输入的长度是不统一的
填写性别,使用 char(1) 因为结果只有是男生 或 女生
3)日期类型
五)DDL表结构的修改
1,添加字段:
alter table 表名 add 字段名 类型(长度)[comment 注释] [约束];
2,修改数据类型
alter table 表名 modify 字段名 新数据类型(长度);
3,修改字段名和数据类型
alter table 表名 change 旧字段名 新字段名 类型(长度)[comment注释] [约束];
4,删除字段
alter table 表名 drop 字段名;
5,修改表名
alter table 表名 rename to 新表名
6,删除表
drop table [if exists] 表名;
7,删除表,并重新创建该表
truncate table 表名; -- 目的:清空原有的数据
2)DML语句
一)添加数据
1,给指定的字段添加对应的数据
insert into 表名(字段名1,字段名2....) values (值1,值2.....);
2,给全部字段添加数据
insert into 表名 values (值1,值2.....);
3,批量添加数据
insert into 表名 (字段名1,字段名2.....) values (值1,值2.....), (值1,值2.....), (值1,值2.....);
insert into 表名 values (值1,值2.....), (值1,值2.....), (值1,值2.....);
注意:
添加的数据必须和表内的数据顺序一致
如果添加的是字符串或日期时间,就必须存放在引号内
添加的数据范围不可超过指定的范围
二)修改数据
修改数据
update 表名 set 字段1=值1, 字段2=值2....[where 条件];
注意:修改语句的条件可以有,也可以没有,如果没有,就直接修改整张表的数据
三)删除数据
删除数据
delete from 表名[where 条件];
注意:删除语句的条件可以有,可以没有,如果没有,就会删除所有数据
delete不能删除某个字段的数据,假如要删除某个字段,就是用updata,将值赋值为null
3)SQL语句
一)基本语法
select 字段列表 from 表名列表 where 条件列表 group by 分组字段列表
having 分组后的条件列表 order by 排序字段列表 limt 分页参数
二)基本查询
1,查询多个字段数据
select 字段名1,字段名2... from 表名;
select * from 表名;
2,设置别名
select 字段名1 (as 别名1),字段名2 (as 别名2)...from 表名;
3,去除重复记录
select distinct 字段列表 from 表名;
三)条件查询(where)
1,语法
select 字段名1,字段名2... from 表名 where 条件列表;
2,条件
四)聚合查询(count,max,min,avg,sum)
将数据看成总体,然后进行数据的统计
count:统计数量 max:最大值 min:最小值 avg:平均值 sum:求和
细节:使用聚合查询时,查询某一列的值最好是不是null,(所有null不进入计算)
比如查询总人数,使用 select count(idcard) from emp; 其中idcard存在null,就不会记录,导致和总的人数不相同,假设要查询总数据量,最好使用 count (*)
语法:select 聚合查询(字段列表) from 表名;
五)分组查询(group by)
语法:select 字段列表 from 表名 [where 条件] group by 分组字段名 [having 分组后过滤 条件]
where和having区别
1,执行时机的不同:where是分组前的操作,不满足where的不参与分组操作,having是对分组 后的数据进行过滤
2,判断条件不同:where不能对聚合函数进行判断,而having可以
执行顺序:where > 聚合函数 > having
分组过后,查询字段一般就是聚合函数和分组字段,查询其他字段没有任何意义
六)排序查询(order by)
语法:select 字段列表 from 表名 order by 字段1 排序方式1,字段2 排序方式2.....;
排序方式:
asc:升序排序(默认值)
desc:降序排序
如果是多字段排序,假如第一个字段是相等的,那么就会按照第二个字段进行排序
七)分页查询(limit)
语法:select 字段列表 from 表名 limit 起始索引,索引数量;
注意:起始索引(页码-1)*索引数量,假设 访问第一页,那索引就是0
分页查询是各个数据库的方言,就是不同数据库写法不同,MySQL就是limit
如果是访问第一页,起始索引可以省略
八)SQL执行顺序
4)DCL语句
作用:用于控制哪一些用户可以访问数据库,并赋予访问权限
一)用户管理操作
1)查询用户
use mysql; ---------->用户信息一般存放在mysql的数据库内
select * from user; -------------->用户信息一般存放在user表内
2)创建用户
create user '用户名'@‘主机名’ identified by ‘密码’;
3)修改用户密码
alter user ‘用户名’@‘主机名’ identified with mysql_native_password by '新密码';
4)删除用户
drop user ‘用户名’@‘主机名’;
注意
主机名可以使用%通配符,表示任意主机都可以访问数据库
一般使用这部分特别少,只有DBA(数据管理员)使用比较多
二)操作权限
主要使用的权限
1,权限控制
查询权限:show grants for ‘用户名’@‘主机名’;
授予权限:grant 权限列表 on 数据库名,表名 to ‘用户名’@‘主机号’;
撤销权限:invoke 权限列表 on 数据库名,表名 from ‘用户名’@‘主机号’;
注意:授予多个权限时,可以使用 , 分割
写数据库名和表名时,可以使用 * 通配符,表示所有数据库和对应的所有表内容
二,函数
1,字符串函数
2,数值函数
3,日期函数
4,流程控制函数
细节:使用case when then else end 中可以使用多个when,假如条件多个时,不能使用 and,or
比如:case 工作地址 when ’北京‘ or ’上海‘ then ’一线城市‘ else ’二线城市‘ end(错误,不知 道为什么,反正我试过,这样使用所有结果都返回’一线城市‘)
正确写法:case 工作地址 when ’北京‘ then ’一线城市‘ when ’上海‘ then ’一线城市‘ else ’二线城市‘ end;
三,约束
1,概念:约束是作用于表中字段上的规则,用于限制存储表中的数据
2,目的:保证数据的准确性,有效性和完整性
示例:一个字段可以对应多个约束
1,外键约束
一)概念
外键是用于两个表之间建立联系,从而保证数据的完整性和依赖性
注意,上述的两个表在数据库层面并未真正做到联系,只是逻辑上具有联系性,必须使用外键使 两个表之间建立联系,才能使数据具有完整性和一致性
二)语法
1)添加外键
1,可以在创建时使用的语法
create table 表名(
字段名 数据类型;
.....
[constraint] [外键名称] foreign key (外键字段名) references 主表 (主表列名)
);
2,创建完表后再进行关联
alter table 表名 add constraint 外键名称 foreign key (外键字段名)references 主表(主表列表)
2)删除外键
alter table 表名 drop foreign key 外键名称;
3)删除/更新操作(一旦删除外键对应的表的信息的操作)
语法:alter table 表名 add constraint 外键名称 foreign key (外键字段名)references 主表(主表列表)on update cascade on delete cascade;
四,多表查询
1,关系模式(三种)
一)1对N
案例:员工和部门之间的关系
关系:一个员工只能对应一个部门,一个部门可以对应多名员工
实现:在多的一方建立外键,关联少的一方,指向一方的主键
二)N对M
案例:学生和选课之间的关系
关系:一个学生可以选多个课程,一个课程可以被多名学生选择
实现:需要一个第三方的表来关联这两个表,而第三个表至少具有两个外键,分别关联两方主键
三)一对一
案例:用户与用户详情的关系
关系:一对一关系,用于单表拆分,将一张表的基础字段放在一张表中,其他详情字段放在另一张表中,以提升操作效率
实现:在任意一方加入外键,关联另一方的主键,并且设置外键为唯一的(unique)
2,多表查询的概述
概述:指从多张表中查询数据
笛卡尔积:笛卡尔积是指数学中,两个集合A和集合B的所有组合情况(在多表查询中,需要消除 无意义的笛卡尔积,示例:集合a数据量为2,集合b数据量为4,那么查询结果就是 2*4=8)
3,多表查询的分类
一)连接查询:
1)内连接:相当于查询a,b交集部分的数据
隐式内连接
select 字段列表 from 表1,表2 where 条件...;
显示内连接
select 字段列表 from 表1 (inner) join 表2 on 连接条件...;
2)外连接:
左外连接:查询左表所有数据,以及两张表交集部分数据(a部分和ab相交的部分)
select 字段列表 from 表1 left [outer] join 表2 on 条件...;
相当于查询表1(左表)所有数据 包含 表1 和 表2 交集部分的数据
右外连接:查询右表所有数据,以及两张表交集部分数据(b部分和ab相交的部分)
select 字段列表 from 表1 right [outer] join 表2 on 条件...;
相当于查询表2(右表)所有数据 包含 表1 和 表2 交集部分的数据
3)自连接:相当于表和自身的连接查询,自连接必须使用表别名
语法:
select 字段列表 from 表1 别名1 join 表2 别名2 on 条件;
4)联合查询:将表1查询的结果和表2查询的结果整合一起
语法:
select 字段列表 from 表A...
union [all]
select 字段列表 from 表B...;
细节:查询多张表使用union返回的结果时,使用的字段列表必须保持一致
union all 是直接将结果整合然后输出,而单用union则会去除重复部分的数据
(我感觉使用or和union其实差不多)
二)子查询:
1)概念
SQL语句中嵌套了select语句,称子查询
select 字段列表 from 表名 where column=(select column from 表名)
在子查询的外面,可以使用select,insert,update...语句
2)根据查询结果不同:
分为:
2,一)标量子查询(子查询返回单个值)
子查询返回结果是单个值(数字,字符串,日期等)
常用符号:> < <> = >= <=
2,二)列子查询(子查询返回一列数据)
子查询返回的结果就是一列(可以是多行)
常用符号:in,not in,any,some,all
2,三)行子查询(子查询返回一行数据)
行子查询返回结果就是一行(可以是多列)
常用操作符:=, <>, in,not in
2,四)表子查询(子查询返回多行多列数据)
查询返回多行多列
常用符号:in
3)根据查询位置不同:
分为:where之后,select之后,from之后
五,事务
1,事务简介
事务是指一些操作,是不可分割的一个工作单位,事务会将一系列操作视作整体,然后一并提交给系统,即这些操作要么一起成功,要么一起失败
示例:假设去转钱,张三转给李四,那么银行会判断张三是否有这些钱,然后减去张三的钱,增 加 李四的钱
但是假如在给李四增加钱之前发生异常,就会停止程序运行,这样会导致张三钱少了,李四钱没变
所以需要事务,将转钱的所有操作视作一个事务,这样,只要在事务内发生异常,事务会回退,数据就不会发生不完整性
细节:默认事务是自动上交的,也就是说,一旦运行一条指令,就会马上提交到系统
就需要我们手动开启或手动关闭事务
2,事务操作
一)关闭自动提交事务
查看事务:select @@autocommit;
设置事务提交方式:set @@autocommit=0;
(细节:1表示自动提交,0表示关闭自动提交)
提交事务:commit(必须执行这一步才会将事务提交上去,否则数据不会改变)
回滚事务:rollback(假设在执行事务抛出异常,必须执行回退操作)
二)手动提交事务
假设不想修改@@autocommit,就可以使用这个手动提交
开启事务:start transaction 或begin
一旦开启事务,就必须执行到commit提交事务,才会将事务提交到系统,否则不会提交
和上述一样,一旦错误,就需要回滚事务rollback
3,事务的四大特性
原子性:事务时不可分割的最小操作单位,要么全部成功,要么全部失败(类似上述的银行转钱 ,查看余额,减少金额和增加金额,就是一个事务,不可分割)
一致性:事务完成时,必须使所有数据保持一致状态(依然类似上述转钱:无论是否执行成功, 最后张三和李四的金额加起来依然不变)
隔离性:数据库系统提供的隔离机制,保证事务在不受外部并发操作影响的独立环境运行(就是 每一个事务都是一个独立的个体,不会相互影响)
持久性:事务一旦发生或者失败,他对数据库中的数据影响是永久性的(因为数据是存储到本地 磁盘的,不会销毁)
4,并发事务问题
概念:多个并发的事务在读取,操作数据发生的问题
一)脏读解释:
事务A先读取数据 id=1(select)
然后执行更新操作 id=1(update)此时事务A还未执行完
而事务B却执行 id=1(select)就会获取到 id=1更新后的数据但是事务A此时还未提交事务,
那么就叫做脏读
二)不可重复读解释:
事务A执行 id=1(select),获取数据假设是2
此时事务A还未完成提交事务,事务B就执行 id=1(update),假设数据改为3,然后提交事务
那么事务A再执行 id=1(select),就会发现现在获取的数据3和一开始的2不一样
那么就是不可重复读
三)幻读解释:
事务A执行 id=1(select) 假设此时 id=1 不存在,那么就读取为null
此时事务A还未执行完,事务B执行 id=1(insert),那么此时数据库就有 id=1 数据
而事务A一开始以为 id=1 数据不存在,就会执行 id=1(insert) 操作,但这样就会报错
那么事务A会检查 id=1 是否存在,假设前面的不可重复读问题已经解决,那么就算数据库存在 id=1 的数据,但因为第一次读取返回结果就是不存在,那么再读取一次依然还是不存在
那么就是幻读
5,事务的隔离级别
细节1:repeatable read是MYSQL默认的,如果使用其他的,可能会不一样
细节2:表中表示的✔就是可能会发生的问题,❌就是不会发生的问题
细节3:serializable隔离能力最高,但效率是最低的
read uncommitted隔离能力最低,但效率是最高的
查看隔离级别:
select @@transaction_isolation;
设置隔离级别
select [session|global] transaction isolation level [ 隔离级别的名字 ]