MySQL数据库应用全解

不羁的心 提交于 2020-08-09 20:24:07

常用引擎的区别

mysql有三种存储引擎分别为

InnoDB 、MyiSAM、Memory

三种存储引擎的区别

InnoDB MyiSAM Memory
mysql5.5之后默认的存储引擎 mysql5.5之前默认的存储引擎 内存存储引擎(很少用到)
支持事务 不支持事务
支持外键(是mysql众多存储引擎中唯一支持外键的) 不支持外键
行级锁(仅对指定行记录进行加锁) 表级锁(对指定表进行加锁)

如何选择存储引擎

首选InnoDB
MySQL5.5之后默认的存储引擎
支持事务,支持外键,支持行级锁
保证数据的完整性,一致性
如果对表的操作有插入和查询,还有更新,删除等操作,建议使用InnoDB



数据库的五种分类

DDL(Data Definition Language)数据定义语言

创建
create database 数据库名;
create database 数据库名 charset 字符集;
create table 表名(列名(字段名) 数据类型,…)
create table 新表 like 老表;
查询
show databases;
show create database 数据库名; 查看建库语句
show tables;
show create table 表名;
desc 表名 ;查看表结构;
修改
alter database 数据库名 charset 字符集;
alter table 表名 add 列名 类型;
alter table 表名 modify 列名 新类型;
alter table 表名 change 旧列名 新列名 新类型;
alter table 表名 drop 列名;
alter table 表名 charset 字符集;
rename table 旧表名 to 新表名;
删除
drop database 数据库名;
drop table 表名;
使用数据库
select database();查看当前使用的数据库
use 数据库; 切换(使用)数据库























DML(Data Manipulation Language)数据操作语言

添加记录
insert into 表名 (列名1,列名2…)values(值1,值2…);
insert into 表名 values(值1,值2…);必须与表列顺序一致,查看desc表名
注意:字符串可以插入一切类型,MySQL底层进行了隐式转换
修改记录
update 表名 set 列名1=新值,列名2=新值…[where条件]
删除记录
delete from 表名 [where 条件] 【这里最好要加上条件
注意:[ ]中的内容可写可不写







DQL(Data Query Language) 数据查询语言

基本查询用法
select * from 表名;
select distinct 列名 from 表名; 去重的关键字distinct
ifnull(列名,默认值)如果该列有值那么就直接返回,如果为null返回默认值
select 列名[as] 列别名 from 表名 [as] 表别名;



高级查询用法
条件查询
select … from 表名 where 条件
关系运算符 > < =…
逻辑运算符 && and , || or ,! not
select … from 表名 where 列名 in(值1,…);
select… from 表名 where 列名 between 较小的值 and 较大的值
select …from 表名 where 列名 is 【not】null
select …from 表名 where 列名 like ‘通配符字符串’
select …from 表名 order by 排序列[asc|desc],排序列[asc|desc]
注意:多字段排序,后面的排序结果是在前面排序的基础之上
聚合函数:count、max、min、sum、avg
select 分组列from 表名 group by 分组列 having 分组后条件过滤
注意:where在分组前进行条件过滤,不能使用聚合函数
having在分组后进行条件过滤,可以使用聚合函数
select …from 表名 limit 开始索引,每页显示个数;














sql执行先后问题

select … from 表名 where 条件 group by 分组 having 分组后条件 order by 排序列[asc|desc] limit 分页;

内连接

  1. 隐式内连接
    select … from 左表,右表 where 连接条件;
  2. 显示内连接
    select…from 左表[inner] join 右表 on 连接条件;

外连接

  1. 左外连接
    select …from 左表 left [outer] join 右表 on 连接条件;
  2. 右外连接
    select …from 右表 right [ outer] join 左表 on 连接条件;

子查询

注意:
子查询结果为单列,肯定作为条件在where后面使用
select …from 表名 where 字段 in(子查询);
子查询结果为多列,肯定作为虚拟表在from后面使用
select …from (子查询) as 表别名;



查询实际应用

首先添加数据库名,数据库表,基本数据

create database text;
use text;
-- 部门表
CREATE TABLE dept (
  id INT PRIMARY KEY auto_increment, -- 部门id
  dname VARCHAR(50), -- 部门名称
  loc VARCHAR(50) -- 部门位置
);

-- 添加4个部门
INSERT INTO dept(id,dname,loc) VALUES 
(10,'教研部','北京'),
(20,'学工部','上海'),
(30,'销售部','广州'),
(40,'财务部','深圳');

-- 职务表
CREATE TABLE job (
  id INT PRIMARY KEY,
  jname VARCHAR(20), -- 职务名称
  description VARCHAR(50) -- 职务描述
);

-- 添加4个职务
INSERT INTO job (id, jname, description) VALUES
(1, '董事长', '管理整个公司,接单'),
(2, '经理', '管理部门员工'),
(3, '销售员', '向客人推销产品'),
(4, '文员', '使用办公软件');

-- 员工表
CREATE TABLE emp (
  id INT PRIMARY KEY, -- 员工id
  ename VARCHAR(50), -- 员工姓名
  job_id INT, -- 职务id  外键
  mgr INT , -- 上级领导
  joindate DATE, -- 入职日期
  salary DECIMAL(7,2), -- 工资 99999.99
  bonus DECIMAL(7,2), -- 奖金 99999.99
  dept_id INT, -- 所在部门编号  外键
  CONSTRAINT emp_jobid_ref_job_id_fk FOREIGN KEY (job_id) REFERENCES job (id),
  CONSTRAINT emp_deptid_ref_dept_id_fk FOREIGN KEY (dept_id) REFERENCES dept (id)
);

-- 添加员工
INSERT INTO emp(id,ename,job_id,mgr,joindate,salary,bonus,dept_id) VALUES 
(1001,'孙悟空',4,1004,'2000-12-17','8000.00',NULL,20),
(1002,'卢俊义',3,1006,'2001-02-20','16000.00','3000.00',30),
(1003,'林冲',3,1006,'2001-02-22','12500.00','5000.00',30),
(1004,'唐僧',2,1009,'2001-04-02','29750.00',NULL,20),
(1005,'李逵',4,1006,'2001-09-28','12500.00','14000.00',30),
(1006,'宋江',2,1009,'2001-05-01','28500.00',NULL,30),
(1007,'刘备',2,1009,'2001-09-01','24500.00',NULL,10),
(1008,'猪八戒',4,1004,'2007-04-19','30000.00',NULL,20),
(1009,'罗贯中',1,NULL,'2001-11-17','50000.00',NULL,10),
(1010,'吴用',3,1006,'2001-09-08','15000.00','0.00',30),
(1011,'沙僧',4,1004,'2007-05-23','11000.00',NULL,20),
(1012,'李逵',4,1006,'2001-12-03','9500.00',NULL,30),
(1013,'小白龙',4,1004,'2001-12-03','30000.00',NULL,20),
(1014,'关羽',4,1007,'2002-01-23','13000.00',NULL,10);

-- 工资等级表
CREATE TABLE salarygrade (
  grade INT PRIMARY KEY,  -- 等级
  losalary INT, -- 最低工资
  hisalary INT -- 最高工资
);

-- 添加5个工资等级
INSERT INTO salarygrade(grade,losalary,hisalary) VALUES 
(1,7000,12000),
(2,12010,14000),
(3,14010,20000),
(4,20010,30000),
(5,30010,99990);

练习

--简单查询
--查询emp表
select * from emp;
--查询emp表吴用的信息
select * from emp where ename="吴用";
--查询emp表的salary的最大值是谁
--1.子查询
SELECT ename,salary from emp WHERE salary=(SELECT MAX(salary) from emp)
--2.直接查询
SELECT ename,salary FROM emp ORDER BY salary DESC LIMIT 1;
--查询emp中的数据工薪在40000到50000之间的数据
SELECT * FROM emp WHERE salary BETWEEN 40000 AND 50000;
--多表查询
-- 1 查询所有员工信息。显示员工编号,员工姓名,工资,职务名称,职务描述
-- 1.1 确定几张表?
SELECT * FROM emp e INNER JOIN job j;
-- 1.2 确定连接条件
SELECT * FROM emp e INNER JOIN job j ON e.job_id = j.id;
-- 1.3 确定显示字段(列)
SELECT e.id,e.ename,e.salary,j.jname,j.description FROM emp e INNER JOIN job j ON e.job_id = j.id;
-- 2 查询所有员工信息。显示员工编号,员工姓名,工资,职务名称,职务描述,部门名称,部门位置
-- 2.1 确定几张表?
SELECT * FROM emp e INNER JOIN job j INNER JOIN dept d;
-- 2.2 确定连接条件
SELECT * FROM emp e INNER JOIN job j INNER JOIN dept d ON e.job_id = j.id AND e.dept_id = d.id; -- 了解
SELECT     -- 推荐
  * 
FROM
  emp e 
  INNER JOIN job j 
    ON e.job_id = j.id 
  INNER JOIN dept d 
    ON e.dept_id = d.id ; 
    
 -- 2.3 确定显示字段
SELECT     
  e.id,
  e.ename,
  e.salary,
  j.jname,
  j.description,
  d.dname,
  d.loc
FROM
  emp e 
  INNER JOIN job j 
    ON e.job_id = j.id 
  INNER JOIN dept d 
    ON e.dept_id = d.id ; 
-- 3 查询所有员工信息。显示员工姓名,工资,职务名称,职务描述,部门名称,部门位置,工资等级
-- 3.1 确定几张表?
SELECT * FROM emp e INNER JOIN job j INNER JOIN dept d INNER JOIN salarygrade sg; 
-- 3.2 确定连接条件
SELECT 
  * 
FROM
  emp e 
  INNER JOIN job j 
    ON e.job_id = j.id 
  INNER JOIN dept d 
    ON e.dept_id = d.id 
  INNER JOIN salarygrade sg 
    ON e.salary BETWEEN sg.losalary 
    AND sg.hisalary ;
-- 3.3 确定显示字段
SELECT 
  e.id,
  e.ename,
  e.salary,
  j.jname,
  j.description,
  d.dname,
  d.loc,
  sg.grade
FROM
  emp e 
  INNER JOIN job j 
    ON e.job_id = j.id 
  INNER JOIN dept d 
    ON e.dept_id = d.id 
  INNER JOIN salarygrade sg 
    ON e.salary BETWEEN sg.losalary 
    AND sg.hisalary ;
-- 4 查询经理的信息。显示员工姓名,工资,职务名称,职务描述,部门名称,部门位置,工资等级
-- 4.1 确定几张表
SELECT * FROM emp e 
	INNER JOIN job j
	INNER JOIN dept d
	INNER JOIN salarygrade;
-- 4.2 确定连接条件 
SELECT * FROM emp e 
	INNER JOIN job j ON e.job_id = j.id
	INNER JOIN dept d ON e.dept_id = d.id
	INNER JOIN salarygrade sg ON e.salary  BETWEEN sg.losalary AND sg.hisalary; 
-- 4.3 确定显示字段
SELECT e.id,e.ename,e.salary,j.jname,j.description,d.dname,d.loc,sg.grade FROM emp e 
	INNER JOIN job j ON e.job_id = j.id
	INNER JOIN dept d ON e.dept_id = d.id
	INNER JOIN salarygrade sg ON e.salary  BETWEEN sg.losalary AND sg.hisalary; 
-- 4.4 确定业务条件
SELECT e.id,e.ename,e.salary,j.jname,j.description,d.dname,d.loc,sg.grade FROM emp e 
	INNER JOIN job j ON e.job_id = j.id
	INNER JOIN dept d ON e.dept_id = d.id
	INNER JOIN salarygrade sg ON e.salary  BETWEEN sg.losalary AND sg.hisalary
	WHERE j.jname = '经理'; 
-- 5 查询出所有部门编号、部门名称、部门位置、部门人数
-- 5.1 查询出部门人数  分组+聚合
SELECT dept_id,COUNT(*) AS total FROM emp GROUP BY dept_id;
-- 5.2 查询的结果作为虚拟表与部门表建立关联
SELECT d.id,d.dname,d.loc,e.total FROM dept d
	LEFT OUTER JOIN (SELECT dept_id,COUNT(*) AS total FROM emp GROUP BY dept_id) AS e
		ON d.id = e.dept_id;

DCL(Data Control Language)数据控制语言

创建用户
create user ‘用户名‘@’ 主机名’ identified by ‘密码’;
注意:
主机名:限定客户端登录ip
指定ip:127.0.0.1
任意ip:%
查看权限
show grants for ‘用户名’@ ‘主机名’;
撤销权限
revoke 权限1,权限2…on 数据库名.表名 from ’ 用户名’ @’ 主机名’
删除用户
drop user ‘用户名’@‘主机名’
密码管理
set password for ‘用户名’@‘主机名’=password(‘新密码’)【超级管理员】
普通用户
set password=password(‘新密码’)














TCL(Transaction Control Language) 事务控制语言

开启事务 start transaction
提交事务 commit
回滚事务 rollback

事务特性

四个属性 解释
原子性:A(atomicity) 如果一个包含多个步骤的业务,被事务管理,那么这些操作要么同时成功,要么同时失败。
一致性:C(consistency) 事务执行前后,保证数据的完整性
隔离性:I(isolation) 多个事务之间,相互独立,不能干扰
持久型:D(durability) 事务一旦提交,同步到数据库磁盘文件,不可逆

事务的隔离性

三种隔离级别 解释
脏读 一个事务中,读取到另一个事务未提交的数据(这个在数据库中是不能让它发生的)
不可重复读 一个事务中,二次读取的内容不一致(在进行修改时)
幻读 一个事务中,二次读取的数量不一致(在进行新增和删除时)

MySQL数据库的隔离级别

级别 名字 隔离级别 脏读 不可重复读 幻读 数据库默认隔离级别
读未提交 read uncommitted
读已提交 read committed Oracle和SQL Server
可重复读 repeatable read MySQL
串行化 serializable

数据库慢查询日志

查看慢查询日志开启情况(mysql默认是关闭的)
show variables like ‘%show_query_log%’;
开启慢查询日志
set global show_query_log=on;
查看慢查询时间配置
show variables like ‘%long_query_time’;
修改慢查询的记录时间
set long_query_time=5
注意:
如果设置变量有global全局更改 ,下次打开生效








数据库的索引

– 创建 普通 索引
create index 索引名 on 表名(列名);
– 创建唯一索引
create unique index 索引名 on 表名(列名);
– 创建普通组合索引
create index 索引名 on 表名(列名1,列名2);
– 创建唯一组合索引
create unique index 索引名 on 表名(列名1,列名2);
– 直接删除
drop index 索引名 on 表名;
– 修改表时删除 【掌握】
alter table 表名 drop index 索引名;
– 添加一个主键,这意味着索引值必须是唯一的,且不能为NULL
alter table 表名 add primary key(列名); – 主键索引名 primary
– 添加唯一索引(除了NULL外,NULL可能会出现多次)
alter table 表名 add unique(列名); – 列名就是索引名
– 添加普通索引,索引值可以出现多次。
alter table 表名 add index(列名); – 列名就是索引名
















索引的创建原则

  1. 存储的文本内容可识别率70%以上
  2. 经常作为条件搜索的字段,建议设置索引
  3. 经常作为多表主外建连接字段,建议设置索引
  4. 经常需要排序的字段,建议设置索引
    注意:不是所有的字段都适合做索引,创建索引也是需要占用磁盘空间的

索引的失效情况

  1. 使用like关键字有遵循左前缀匹配规则
  2. 尽量避免使用or,如果条件有一个没有索引,那么会进行全表扫描
  3. 在索引列上进行计算
  4. 在索引列上进行隐式转换
  5. 使用!=、<>、not in、is not null时

索引的数据结构

有哪些数据结构及特点

  1. 数组:遍历查找快,适用于内存小量数据
  2. 链表:增删快,查找慢,适用于内存小量数据
  3. 二叉树:一个父节点下只有二个子节点,特点:左边子节点比父节点小,右表的子节点比父节点大
  4. 红黑树:平衡二叉树(左旋和右旋),保证每一个父节点都有二个子节点
  5. BTree:多路(多叉)平衡搜索树,可以有效控制树的高度
  6. B+Tree:MySQL用的这个数据结构,(非叶子节点不存储数据,叶子节点没有指针)
  7. Hash:散列 key-value (无序,根据key查找value超快,范围查找速度慢)
    1.7:数组+链表
    1.8:数组+红黑树(如果碰撞数量 <8 ,还是使用链表 )
    hash碰撞


目的只有一个控制树高度,减少磁盘IO

MySQL中的B+Tree

在这里插入图片描述
查看mysql中索引节点的大小
show global status like ‘innodb_page_size’;
在这里插入图片描述


MySQL函数

字符串函数

  1. 函数:CONCAT(s1,s2…sn)
    描述:字符串 s1,s2 等多个字符串合并为一个字符串
    实例:SELECT CONCAT(“传”, “智”, “播”, “客”);

  2. 函数:CHAR_LENGTH(str)
    描述:返回字符串 str 的字符数
    实例:SELECT CHAR_LENGTH(“传智播客”);

  3. 函数:LENGTH(str)
    描述:返回字符串 s 的字节数
    注意:mysql编码UTF8 中文占用3个字节
    实例:SELECT LENGTH(“传智播客”) ;


  4. 函数:UCASE(s) | UPPER(s)
    描述:将字符串转换为大写
    实例:SELECT UCASE(“itcast”);

  5. 函数:LCASE(s) | LOWER(s)
    描述:将字符串转换为小写
    实例:SELECT LCASE(“ITCAST”);

  6. 函数:LOCATE(s1,s)
    描述:从字符串 s 中获取 s1 的开始位置
    实例:SELECT LOCATE(‘he’,‘itheima’);

  7. 函数:TRIM(str) | LTRIM(str) | RTRIM(str)
    描述:字符串去空格
    实例:SELECT TRIM(" 传智人 ");

  8. 函数:REPLACE(s,s1,s2)
    描述:将字符串 s2 替代字符串 s 中的字符串 s1
    实例:SELECT REPLACE(‘abc’,‘a’,’*’);

  9. 函数:SUBSTR(s, start, length)
    描述:从字符串 s 的 start 位置截取长度为 length 的子字符串
    实例:SELECT SUBSTR(“itcast”, 2, 3);

  10. 函数:STRCMP(str1,str2)
    描述:比较字符串大小,左大于右时返回1,左等于右时返回0,,左小于于右时返回-1,
    实例:SELECT STRCMP(“a”,“b”);

日期函数

  1. 函数:NOW() | CURDATE() | CURTIME()
    描述:获取系统当前日期时间、日期、时间
    实例:SELECT NOW();

  2. 函数:YEAR(DATE) | MONTH(DATE) | DAY(DATE)
    描述:从日期中选择出年、月、日
    实例:SELECT YEAR(NOW());

  3. 函数:LAST_DAY(DATE)
    描述:返回月份的最后一天
    实例:SELECT LAST_DAY(NOW())

  4. 函数:ADDDATE(DATE,n) | SUBDATE(DATE,n)
    描述:计算起始日期 DATE 加(减) n 天的日期
    实例:SELECT ADDDATE(NOW(),10);

  5. 函数:QUARTER(DATE)
    描述:返回日期 DATE 是第几季节(季度),返回 1 到 4
    实例:SELECT QUARTER(NOW());

  6. 函数:DATEDIFF(d1,d2)
    描述:计算日期 d1->d2 之间相隔的天数
    实例:SELECT DATEDIFF(‘2019-08-01’,‘2019-07-01’);

  7. 函数:DATE_FORMAT(d,f)
    描述:按表达式 f的要求显示日期 d
    实例:SELECT DATE_FORMAT(NOW(),’%Y-%m-%d’);

数据函数

  1. 函数:ABS(x)
    描述:返回 x 的绝对值  
    实例:SELECT ABS(-1);

  2. 函数:CEIL(x) | FLOOR(x)
    描述:向上(下)取整
    实例:SELECT CEIL(1.5);

  3. 函数:MOD(x,y)
    描述:返回x mod y的结果,取余
    实例:SELECT MOD(5,4);

  4. 函数:RAND()
    描述:返回 0 到 1 的随机数
    实例:SELECT RAND();

  5. 函数:ROUND(x)
    描述:四舍五入
    实例:SELECT ROUND(1.23456);

  6. 函数:TRUNCATE(x,y)
    描述:返回数值 x 保留到小数点后 y 位的值
    实例:SELECT TRUNCATE(1.23456,3);

高级函数

case表达式【相当于java中swtich语句】

– 语法
SELECT
CASE [字段,值]
WHEN 判断条件1
THEN 希望的到的值1
WHEN 判断条件2
THEN 希望的到的值2
ELSE 前面条件都没有满足情况下得到的值
END
FROM
table_name;









if表达式

– 语法
SELECT IF(1 > 0,‘true’,‘false’) from table_name;

cast(显示)类型转换【了解】

– 语法
SELECT CAST(参数 AS 类型);

– 类型
字符型:CHAR
日期 : DATE
时间: TIME
日期时间型 : DATETIME
浮点数 : DECIMAL
整数 : SIGNED





数据库的优化

  1. 硬件:更快的IO,更多的内存
  2. 系统配置(my.ini):可以通过配置MySQL的一些参数来提高MySQL性能,例如:最大连接数,数据库能占的内存大小,内存使用什么算法,是否支持线程池
  3. 数据库表结构:

表设计:根据数据三范式来进行表的设计

  1. 第一范式(1NF)
    要求:
    每一列不能再拆分

  2. 第二范式(2NF)
    要求:
    1.一张表只描述一件事情
    2.表中的每一个普通列都依赖于主键


  3. 第三范式(3NF)
    要求:
    从表的外键必须使用主表的主键

表字段类型的选择
1.选择更小的数据类型(数据库类型越小,占用的磁盘空间,内存和cpu缓存更少)
2.选择简单的数据类型(越简单的数据类型,需要的cpu周期越少,时间,IP都可以用数值类型来表述)
3.尽量避免null,null在查询的时候会比较复杂
4.如果对象数值有进度要求,建议使用decimal



数据库5大约束
primary key:主键约束(唯一识别一条记录)
unique:唯一索引(数据唯一)
default:默认值(提供默认值)
not null:非空约束(不能为null)
forgein key:设置外键约束




SQL语句的优化
1.对每一条sql查询都进行优化,尽量避免全表扫描(explain sql 查询语句),考虑在where子句后或者order by 后的列进行建立索引
2.在where子句后尽量避免对null值的判断,以及!=,or,in,ont in,like,表达式函数,这些操作会导致放弃索引查询,而采用全表扫描
3.不要在where子句=左边进行函数,算数运算或者其他的表达式运算,否则MySQL就无法正确的使用索引
4.在使用索引查询时,如果是多列索引,必须要使用最左前缀,没有使用,就会用全表扫描
5.不要写没有意义的查询




易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!