MySQL

it2022-05-09  77

概念

什么是SQL?     * Structured Query Language 结构化查询语言     * 其实就是定义了操作所有关系型数据库的规则。每一种数据库操作的方式存在不一样的地方,称为“方言”;SQL通用语法      1)SQL语句可以单行或多行书写,以分号结尾      2)SQL 中不区分大小写,关键字中认为大写和小写是一样的      3)3种注释:         a)–空格 单行注释         b)# 单行注释(MySQL特有)         c)/* */ 多行注释SQL分类      1)Data Definition Language (DDL 数据定义语言) 如:建库,建表 ;关键字:create、drop、alter等;      2)Data Manipulation Language(DML 数据操纵语言),如:对表中的记录操作增删改;关键字:insert、delete、update等      3)Data Query Language(DQL 数据查询语言),如:对表中的查询操作 ;关键字:select、where等      4)Data Control Language(DCL 数据控制语言),如:对用户权限的设置 ;关键字:GRANT、REVOKE等

DDL:操作数据库、表

操作数据库:CRUD

C(create):创建

创建数据库 create database 数据库名称;创建数据库,判断不存在,再创建 create database if not exists 数据库名称;创建数据库并指定字符集 create database 数据库名称 character set 字符集名;练习:创建db4数据库,判断是否存在,并指定字符集为gbk create database if not exists db4 character set gbk;

R(Retrieve):查询

查询所有数据库的名称 show databases;查询某个数据库(或表)的字符集:查询某个数据库的创建语句 show create database 数据库名称;

U(update):修改

修改数据库的字符集 alter database 数据库名称 character set 字符集名称;

D(Delete)删除

删除数据库 drop database 数据库名称;判断数据库是否存在,存在在删除 drop database if exists 数据库名称;

使用数据库

查询当前正在使用的数据库名称 select database();使用数据库 use 数据库名称;

操作表:CRUD

C(create):创建

语法 CREATE TABLE 表名 ( 字段名 1 字段类型 1, 字段名 2 字段类型 2 );注意,最后一列,不需要加逗号(,)复制表:create table 表名 like 被复制的表名数据库类型 int:整数类型 如:age intdouble:小数类型 如:score double(5,2)date:日期,只包含年月日,yyyy-MM-dddatatime:日期,包含年月日时分秒,yyyy-MM-dd HH:mm:sstimestamp:时间戳类型,包含年月日时分秒,yyyy-MM-dd HH:mm:ss 如果将来不给这个字段赋值,或赋值为null,则默认使用当前的系统时间,来自动赋值varchar:字符串 如:name varchar(20):姓名最大为20个字符 zhangsan 8个字符

R(Retrieve):查询

查询某个数据库中所有表的名称 show tables查询表结构 desc 表名

U(update):修改

修改表名 alter table 表名 rename to 新的表名修改表的字符集 alter table 表名 character set 字符集名称添加1列 alter table 表名 add 列名 数据类型修改列名称、类型 alter table 表名 change 列名 新列名 新数据类型 alter table 表名 modify 列名 新数据类型删除列 alter table 表名 drop 列名

D(Delete)删除

删除表 drop table 表名;判断是否存在,再删除 drop table if exists 表名

DML:增删改表中数据

添加数据

语法: insert into 表名(列名1,列名2,列名3...,列名n) values(值1,值2,....,值n)注意 1)如果表名后,不定义列名,则默认给所有列添加值 insert into 表名 values(值1,值2,值3); 2)除了数字类型,其他类型需要使用引号(单双都可以)引起来

删除数据

语法 delete from 表名 [where 条件]注意 1)如果不加条件,则删除表中所有记录; 2)若真想删除表中所有记录: 第一种方法:delete from 表名;(不推荐使用,有多少条记录就会执行多少次删除操作) 第二种方法:truncate table 表名;(推荐使用,效率高,先删除表,然后在创建一张一模一样的表)

修改数据

语法 update 表名 set 列名1=值1,列名2=值2,...[where 条件];注意: 1)如果不加任何条件,则会将表中所有记录全部修改

DQL:查询语句7

select * from 表语法 select 字段列表 from 表名列表 where 条件列表 group by 分组字段 having 分组之后的条件 order by 排序 limit 分页限定

基础查询

查询多个字段 select 字段名1,字段名2,....from 表名; 若要查询全部字段,则用*号代替;去除重复:distinct select distinct 字段名 from 表名;计算列 1)一般可以使用四则运算计算一些列的值。(一般只会进行数值型的计算) 2)ifnull(表达式1,表达式2):null参与的运算,计算结果都为null    表达式1:哪个字段需要判断是否为null    表达式2:如果该字段为null后的替换值

如果有null参与运算,计算结构都为null select math,english,math+ifnull(english,0) from student;

起别名 用 as,as也可以省略用空格代替

select math as 数学成绩 from student;

条件查询

where 子句后跟条件>、<、>=、<=、=、<>(不等于)、!=(不等于)between…and…in(集合)LIKE(模糊查询)is null(空)、is not null(非空)and 或 &&or 或 ||not 或 !

查询年龄18、22、25岁的学生信息 slect * from student where age=18 OR age=22 OR age=25; 或select * from student where age IN(18,22,25);

模糊查询

LIKE(模糊查询)占位符: _ :单个字符 %:多个字符 查询姓名第二字是“化”的人 select * from student where name LIKE '_化%'; --单引号或双引号都行查询姓名是3个字的人 select * from student where name LIKE "___";查询姓名中包含德的人 select * from student where name LIKE '%德%';

排序查询

语法:order by 子句 order by 排序字段1 排序方式1,排序字段2 排序方式2;排序方式 ASC:升序,默认的 DESC:降序注意:如果有多个排序条件,则当前边的条件值一样时,才会判断第二个条件;

聚合函数

聚合函数:将一列数据作为一个整体,进行纵向的计算 count:统计非空记录的个数 1 一般选择非空列:主键 2 或使用count(*)统计(不推荐)max:计算最大值min:计算最小值sum:计算和avg:计算平均值 注意:聚合函数的计算,排除null值解决方案 选择不包含非空的列进行计算IFNULL函数:IFNULL(列名,0):将该列中的null替换成0

分组查询

语法:group by 分组字段注意: 1)分组之后可以查询的字段:分组字段、聚合函数 2)where 和 having 的区别:       1. where在分组之前限定,如果不满足条件,则不参与分组。having 在分组之后进行限定,如果不满足结果,则不会被查询出来;       2. where后不可以跟聚合函数,having可以进行聚合函数的判断;使用:

按照性别分组,分别查询男、女同学的平均分、人数 。要求:分数低于70分的人,不参与分组,分组之后,人数要大于2人 select sex,avg(math),count(id) from student where math>70 group by sex having count(id)>2;

分页查询

语法:limit 开始的索引,每页显示的条数公式:开始的索引=(当前的页码 - 1) * 每页显示的条数注意:limit 是一个MySQL的方言

每页显示3条记录 select * from student limit 0,3; --第1页 select * from student limit 3,3; --第2页

约束

概念:对表中的数据进行规定,保证数据的正确性、有效性和完整性;分类 1)主键约束:primary key 2)非空约束:not null 3)唯一约束:unique 4)外键约束:foreign key

非空约束

1. 创建表时添加非空约束 create table stu( id int, name varchar(20) not null --name非空 ); 2. 创建表完后,删除name的非空约束 alter table stu modify name varchar(20); 3. 创建表完后,添加非空约束 alter table stu modify name varchar(20) not null;

唯一约束

唯一,即值不能重复 1. 创建表时,添加唯一约束 create table stu( id int, name varchar(20) unique --name不能重复 ); 2. 注意:MySQL中,唯一约束限定的列的值可以有多个null; null值代表不确定,多个null值代表多个不确定的值,所以唯一约束限定的列可以存在多个null; 3. 删除唯一约束(和删除非空约束的命令是不一样的) alter table stu drop index name; 4. 在创建表后,添加唯一约束 alter table stu modify name varchar(20) unique;

主键约束

含义:非空且唯一;一张表只能有一个字段为主键主键就是表中记录的唯一标识 1. 创建表时,添加主键 create table stu( id int primary key, name varchar(20) ); 2. 删除主键 alter table stu drop primary key; 3. 创建完表后,添加主键 alter table stu modify id int primary key; 4. 自动增长:如果某一列是数值类型的,使用auto_increment可以完成值的自助增长 4.1 创建表时,添加主键约束,并设置主键自动增长 create table stu( id int primary key auto_increment, name varchar(20) ); 4.2 删除自动增长 alter table stu modify id int; 4.3 添加自动增长 alter table stu modify id int auto_increment;

外键约束与及外键级联操作

语法: 1. 添加外键 create table 表名( ... 外键列 constraint 外键名称 foreign key (外键列名称) references 主表名称(主表列名称) --【constraint 外键名称】 可以省略不写,不写则系统自动生成外键名称 ); 2. 删除外键 alter table 表名 drop foreign key 外键名称; 3. 创建表之后添加外键 alter table 表名 add constraint 外键名称 foreign key (外键列名称) references 主表名称(主表列名称); 4. 级联操作 4.1 分类 1)级联更新:on update cascade 2)级联删除:on delete cascade 4.2 添加级联操作 语法:alter table 表名 add constraint 外键名称 foreign key (外键列名称) references 主表名称(主表列名称) on update cascade on delete cascade 使用: 7. 创建表时,添加外键约束 -- 前提:一个部门包含多个员工 create table department( --创建部门表 id int primary key auto_increment, dep_name varchar(20), -- 部门名称 dep_location varchar(20) --部门所在地址 ); create table employee( id int primary key auto_increment, name varchar(20), dep_id int --dep_id可以为null,但不可以为department(id)中不存在的值 constraint emp_dept_fk foreign key (dep_id) references department(id) ); 8. 删除外键列 alter table employee drop foreign key emp_dept_fk;

多表操作

分类 1)一对一:人和身份证 2)一对多(多对一):部门和员工 3)多对多:学生和课程实现方式: 1)一对多关系:在多的一方建立外键,指向一的一方的主键;(多:员工 一:部门) 2)多对多关系:多对多关系实现需要借助第三张中间表,中间表至少包含两个字段,这两个字段(联合主键)作为第三张表的外键,分别指向另外两张表的主键; 3)一对一关系:一对一关系实现,可以在任意一方添加唯一外键指向另一方的主键

三大范式

概念:设计关系数据库时,遵从不同的规范要求,设计出合理的关系型数据库,这些不同的规范要求被称为不同的范式,各种范式呈递次规范,越高的范式数据库冗余越小。目前关系数据库有六种范式:第一范式(1NF)、第二范式(2NF)、第三范式(3NF)、巴斯-科德范式(BCNF)、第四范式(4NF)和第五范式(5NF,又称完美范式)。分类 1)第一范式:数据库表的每一列都是不可分割的原子数据项,而不能是集合,数组 2)第二范式:在1NF的基础上,非码属性必须完全依赖于候选码(在1NF基础上消除非主属性对主码的部分函数依赖)

几个概念

函数依赖:A -->B,如果通过A属性(属性组)的值,可以确定唯一B属性的值,则B依赖于A; 例如:学号–>姓名 (学号,课程名称)–>课程分数完全函数依赖:A–>B,如果A是一个属性组,则B属性值的确定需要依赖于A属性组中的所有的属性值 例如:(学号,课程名称)–>课程分数部分函数依赖:A–>B,如果A是一个属性组,则B属性值的确定只需要A属性组中某一些值即可; 例如:(学号,课程名称)–>姓名传递函数依赖:A–>B,B–>C,如果通过A属性(属性组)的值,可以确定唯一B属性的值,再通过B属性(属性组)的值,可以确定唯一C属性的值,则称C传递函数依赖于A 例如:学号–>系名 ,系名–>系主任码:如果在一张表中,一个属性或一个属性组,被其他所有属性完全依赖,则称这个属性(属性组)为该表的码 例如:该表中的码为:(学号,课程名称) 主属性:码属性组中的所有属性 非主属性:除码属性组中的属性

3)第三范式:在2NF基础上,任何非主属性不依赖于其他非主属性(在2NF基础上消除传递依赖)

三大范式详解

给定一张表,如下图:

可以看出,这张给定的表不符合1NF,因为1NF要求数据库表的每一列都是不可分割的原子数据项,而该表中“系”这一列包含两个子列,可以分割;

将上图化成符合1NF的表,如下图:

从上表可以看出,1NF还是存在3个比较严重的问题;

将1NF表去除部分依赖,化为2NF表,如下图:

从上图可以看出,2NF消除了数据冗余问题,但还是存在其他问题

从2NF表中消除部分传递依赖,化为3NF表,如下图:

从上图可以看到,3NF表很好的消除了数据添加和数据删除所引起的问题。

多表查询

select 列名列表 from 表名列表 where 条件列表 存在问题: 1. 假设部门dept表中有3个记录,每个记录代表一个部门 假设员工employee表中有5个记录,每个记录代表一个员工信息 2. 多表查询:select * from dept,employee 3. 查询结果:会出现15条记录,明显不是我们要的结果 4. 原因:15条记录是dept表中的3个记录employee表中的5个记录做笛卡尔积所得的结果 要完成多表查询,就要消除笛卡尔积所产生的无用数据多表查询的分类: 1)内连接查询 2)外连接查询 3)子查询

内连接查询

内连接:查询的是两个表的交集部分隐式内连接:使用where条件消除无用数据 例子: -- 查询所有员工信息和对应的部门信息 SELECT * FROM emp,dept WHERE emp.`dept_id` = dept.`id`; -- 查询员工表的名称,性别。部门表的名称 SELECT emp.name,emp.gender,dept.name FROM emp,dept WHERE emp.`dept_id` = dept.`id`; SELECT t1.name, -- 员工表的姓名 t1.gender,-- 员工表的性别 t2.name -- 部门表的名称 FROM emp t1, dept t2 WHERE t1.`dept_id` = t2.`id`; 显式内连接: 语法: select 字段列表 from 表名1 [inner] join 表名2 on 条件 SELECT * FROM emp INNER JOIN dept ON emp.`dept_id` = dept.`id`;SELECT * FROM emp JOIN dept ON emp.`dept_id` = dept.`id`; 使用内连接查询基本思路: 1)从哪些表中查询数据 2)条件是什么 3)查询哪些字段

外连接查询

左外连接 1)语法:select 字段列表 from 表1 left [outer] join 表2 on 条件; 2)查询的是左表所有数据以及其交集部分。右外连接 1)语法:select 字段列表 from 表1 right [outer] join 表2 on 条件; 2)查询的是右表所有数据以及其交集部分。 -- 左外连接举例 -- 查询所有员工信息,如果员工有部门,则查询部门名称,没有部门,则不显示部门名称 SELECT t1.*,t2.`name` FROM emp t1 LEFT JOIN dept t2 ON t1.`dept_id` = t2.`id`; -- 右外连接举例 -- dept表的全部数据与及和emp表的交集数据,所以这里若员工没有部门信息,则该员工不会出现在结果当中 SELECT * FROM dept t2 RIGHT JOIN emp t1 ON t1.`dept_id` = t2.`id`;

子查询

概念:查询中嵌套查询,称嵌套查询为子查询 -- 查询工资最高的员工信息 -- 1 查询最高的工资是多少 9000 SELECT MAX(salary) FROM emp; -- 2 查询员工信息,并且工资等于9000的 SELECT * FROM emp WHERE emp.`salary` = 9000; -- 一条sql就完成这个操作。子查询 SELECT * FROM emp WHERE emp.`salary` = (SELECT MAX(salary) FROM emp); 子查询的不同情况 1)子查询的结果是单行单列的 2)子查询的结果是多行单列的 3)子查询的结果是多行多列的

子查询的结果是单行单列的

子查询可以作为条件,使用运算符去判断。 运算符: > 、>=、 < 、<=、 = -- 查询员工工资小于平均工资的人 SELECT * FROM emp WHERE emp.salary < (SELECT AVG(salary) FROM emp);

子查询的结果是多行单列的

子查询可以作为条件,使用运算符in来判断(多行单列的结果集可以作为一个集合) -- 查询'财务部'和'市场部'所有的员工信息 SELECT id FROM dept WHERE NAME = '财务部' OR NAME = '市场部';--查询返回的结果为2和3 SELECT * FROM emp WHERE dept_id = 3 OR dept_id = 2; --根据2和3得到员工信息 -- 子查询 SELECT * FROM emp WHERE dept_id IN (SELECT id FROM dept WHERE NAME = '财务部' OR NAME = '市场部');

子查询的结果是多行多列的

子查询可以作为一张虚拟表参与查询 -- 查询员工入职日期是2011-11-11日之后的员工信息和部门信息 -- 子查询 SELECT * FROM dept t1 ,(SELECT * FROM emp WHERE emp.`join_date` > '2011-11-11') t2 WHERE t1.id = t2.dept_id; -- 普通内连接 SELECT * FROM emp t1,dept t2 WHERE t1.`dept_id` = t2.`id` AND t1.`join_date` > '2011-11-11'

事务

概念:如果一个包含多个步骤的业务操作,被事务管理,那么这些操作要么同时成功,要么同时失败。操作: 1. 开启事务: start transaction;(写在sql语句之前) 2. 回滚:rollback;(写在多个sql语句之后) 3. 提交:commit;(写在多个sql语句之后)MySQL数据库中事务默认自动提交 事务提交的两种方式: * 自动提交:(不开启事务,若开启了事务则不会自动提交) * mysql就是自动提交的 * 一条DML(增删改)语句会自动提交一次事务。 * 手动提交: * Oracle 数据库默认是手动提交事务(写完一条DML(增删改)语句后要加上commit;语句才算真正的执行了DML(增删改)语句) * 需要先开启事务,再提交 * 修改事务的默认提交方式: * 查看事务的默认提交方式:SELECT @@autocommit; -- 1 代表自动提交 0 代表手动提交 * 修改默认提交方式: set @@autocommit = 0;

事务的四大特征

原子性:是不可分割的最小操作单位,要么同时成功,要么同时失败。持久性:当事务提交或回滚后,数据库会持久化的保存数据。隔离性:多个事务之间。相互独立。一致性:事务操作前后,数据总量不变

事务的隔离级别

概念:多个事务之间是隔离的,相互独立的。但是如果多个事务操作同一批数据,则会引发一些问题,设置不同的隔离级别就可以解决这些问题。存在问题: 1)脏读:一个事务,读取到另一个事务中没有提交的数据 2)不可重复读(虚读):在同一个事务中,两次读取到的数据不一样。 3)幻读:一个事务操作(DML)数据表中所有记录,另一个事务添加了一条数据,则第一个事务查询不到自己的修改。隔离级别 1)read uncommitted:读未提交     * 产生的问题:脏读、不可重复读、幻读 2)read committed:读已提交 (Oracle)     产生的问题:不可重复读、幻读 3)repeatable read:可重复读 (MySQL默认)     产生的问题:幻读 4)serializable:串行化(对表加锁)     可以解决所有的问题注意:隔离级别从小到大安全性越来越高,但是效率越来越低数据库查询隔离级别: select @@tx_isolation;数据库设置隔离级别:(设置之后需要关闭连接重新打开才会生效) set global transaction isolation level 级别字符串;演示(read uncommitted) 事务未提交: 查看未提交事务: 演示(read committed) 事务1: 事务2: 演示(repeatable read) 事务1: 事务2: 演示(serializable) 事务1: 事务2:

DCL:管理用户,授权

管理用户

1. 添加用户: 语法:CREATE USER '用户名'@'主机名' IDENTIFIED BY '密码'; 2. 删除用户: 语法:DROP USER '用户名'@'主机名'; 3. 修改用户密码: UPDATE USER SET PASSWORD = PASSWORD('新密码') WHERE USER = '用户名'; UPDATE USER SET PASSWORD = PASSWORD('abc') WHERE USER = 'lisi'; SET PASSWORD FOR '用户名'@'主机名' = PASSWORD('新密码'); SET PASSWORD FOR 'root'@'localhost' = PASSWORD('123'); * mysql中忘记了root用户的密码? 1) cmd -- > net stop mysql 停止mysql服务 * 需要管理员运行该cmd 2) 使用无验证方式启动mysql服务: mysqld --skip-grant-tables 3) 打开新的cmd窗口,直接输入mysql命令,敲回车。就可以登录成功 4) use mysql; 5) update user set password = password('你的新密码') where user = 'root'; 6) 关闭两个窗口 7) 打开任务管理器,手动结束mysqld.exe 的进程 8) 启动mysql服务 9) 使用新密码登录。 4. 查询用户: -- 1. 切换到mysql数据库 USE mysql; -- 2. 查询user表 SELECT * FROM USER; * 通配符: % 表示可以在任意主机使用用户登录数据库

权限管理

1. 查询权限: -- 查询权限 SHOW GRANTS FOR '用户名'@'主机名'; SHOW GRANTS FOR 'lisi'@'%'; 2. 授予权限: -- 授予权限 grant 权限列表 on 数据库名.表名 to '用户名'@'主机名'; -- 给张三用户授予所有权限,在任意数据库任意表上 GRANT ALL ON *.* TO 'zhangsan'@'localhost'; 3. 撤销权限: -- 撤销权限: revoke 权限列表 on 数据库名.表名 from '用户名'@'主机名'; REVOKE UPDATE ON db3.`account` FROM 'lisi'@'%';

最新回复(0)