目录
一、数据库和SQL概述
1. 数据库简介
数据库指的是长期存在计算机内、有组织、可共享的、大量数据的集合。数据是按照特定的数据模型来组织、存储在数据库中的。
2. 数据库好处
(1)(与文件一样)持久化数据到本地 (数组、集合存储到内存,断电数据消失)
(2)可以实现结构化查询,方便管理
3. 数据库相关概念
-
DB(database):数据库,保存一组有组织的数据的容器
-
DBMS(Database Management System):数据库管理系统,又称为数据库软件(产品),用于管理DB中的数据
-
常见DBMS:MySQL、Oracle、DB2、SqlServer等
-
-
SQL:结构化查询语言,用于和数据库通信的语言
4. 数据库三层结构
数据库存储数据的特点:
(1)将数据放到表中,表再放到库中
(2)一个数据库中可以有多个表,每个表都有一个的名字,用来标识自己。表名具有唯一性。
(3)表具有一些特性,这些特性定义了数据在表中如何存储,类似java中“类”"的设计。
(4)表由列组成,我们也称为字段。所有表都是由一个或多个列组成的,每一列类似java 中的”属性”。
(5)表中的数据是按行存储的,每一行类似于java中的“对象”。
5. SQL的语言分类
-
DQL(Data Query Language):数据查询语言,用来查询数据库中表的记录(数据)
关键字:select, where 等
-
DML(Data Manipulate Language):数据操纵语言,用于添加、删除、修改数据库记录,并检查数据完整性
关键字:insert, delete, update 等
-
DDL(Data Define Languge):数据定义语言,用于库和表的创建、修改、删除
关键字:create, drop,alter等
-
TCL(Transaction Control Language):事务控制语言
-
DCL(Data Control Language):数据控制语言,管理数据库,如用户权限
二、MySQL介绍和安装
1. MySQL介绍
MySQL 是一款安全、跨平台、高效的,并与 PHP、Java 等主流编程语言紧密结合的数据库系统。该数据库系统是由瑞典的 MySQL AB 公司开发、发布并支持,由 MySQL 的初始开发人员 David Axmark 和 Michael Monty Widenius 于 1995 年建立的
2. MySQL安装
注意:安装路径不要包含中文或者空格等特殊字符(使用纯英文目录),默认安装在C盘。
3. MySQL服务的启动和停止
方式一:计算机——右击管理——服务——MySQL
方式二:通过管理员身份运行cmd命令提示行 net start mysql(启动服务)
net stop mysql(停止服务)
4. MySQL服务的登录和退出
方式一:通过MySQL自带的客户端 只限于root用户
方式二:通过cmd命令提示行关闭,未配置MySQL环境变量,需在MySQL安装的bin下启动cmd
登录: mysql 【-h主机名 -P端口号 】-u用户名 -p密码
退出: exit或ctrl+C
5. MySQL的语法规范
不区分大小写
使用“;”结尾
各子句一般分行写
关键字不能缩写也不能分行
合理使用缩进
注释 单行注释1:#注释文字
单行注释2:-- 注释文字
多行注释:/* 注释文字 */
6. MySQL的常见命令
(1)查看当前所有的数据库: show databases;
(2)打开指定的库:use 库名;
(3)查看当前库的所有表:show tables;
(4)查看其他库的所有表:show tables from 库名;
(5)创建表:creat table 表名(列名 列类型,列名 列类型 ,...);
(6)查看表结构:desc 表名;
(7)查看服务器版本:方式一:命令行, mysql --version;
方式二:登录到mysql服务端,select version();
三、DQL语言(数据查询语言)
MySQL语句的大致执行顺序如下:
(1)FROM:指定要查询的表。
(2)JOIN:根据指定的条件,将两个或多个表合并为一个结果集。
(3)ON:JOIN的连接条件,符合连接条件的行会被记录在虚拟表中。
(4)WHERE:对查询结果进行筛选,只保留满足指定条件的行。
(5)GROUP BY:将结果集按照指定的列进行分组。
(6)avg,sum…:常用的 Aggregate 函数
(7)HAVING:对分组后的结果进行筛选,只保留满足指定条件的分组。
(8)SELECT:选择要查询的列。
(9)DISTINCT:对查询结果进行去重。
(10)UNION:将两个或多个查询结果集合并为一个结果集。
(11)ORDER BY:按照指定的列对结果集进行排序。
(12)LIMIT:指定查询结果的行数限制。
1. 简单查询
语法:
select 查询列表 from 表名;
特点:
a.查询列表可以是:表中的字段、常量值、表达式、函数
b.查询的结果是一个虚拟的表格
(1)基础查询
a. 单个字段的查询
select last_name from employees;
b. 多个字段的查询
select 字段名1,字段名2... from 表名;
select last_name,salary,email from employees;
* 注意:如果查询所有字段,则可以使用*来替代字段列表。
select * from employees;
c. 起别名:
便于理解,如果要查询的字段有重名的情况,使用别名可以区分开来
as(可以省略)
或
select last_name 姓 from employees;
注意:where后面是不能使用查询字段的别名的,而group by、having、order by后面可以使用字段的别名。
原因:这与sql语句执行的顺序是有关系的,当出现select 以及where时,表明这是查询条件语句,那么先执行where,在select中对字段设置别名,此时where字段如果使用了别名,它是查询不到该字段的,因此where后面必须使用列名(字段名),当查询结果出来后,再根据别名进行分组、排序都是可以的。
d. 去除重复:
distinct
select distinct last_name from employees;
e. +号的作用
java中的+号:
运算符,两个操作数都为数值型
连接符,只要有一个操作数为字符串
mysql中的+号:
仅仅只有一个功能:运算符
select 100+90;两个操作数都为数值型,则做加法运算
select '123'+90;其中一方为字符型,试图将字符型数值转换成数值型,如果转换成功,则继续做加法运算
select 'john '+90;如果转换失败,则将字符型数值转换成0
select null+10;只要其中一方为null,则结果肯定为null
(2)其他查询
a. 查询常量值
SELECT 100;
SELECT ' john ' ;
b. 查询表达式
SELECT 100%98;
c. 查询函数
SELECT VERSION() ;
2. 条件查询
语法:
select 查询列表 from 表名 where 筛选条件;
分类:
(1)按条件表达式筛选
条件运算符: > < = != <> >= <=
select * from employees where salary > 20000;
*注意: != <> 不能判断null值
(2)按逻辑表达式筛选
逻辑运算符: 用于连接条件表达式
&& ll ! and or not
select * from employees where salary > 20000 and department_id <>90;
(3)模糊查询
like
* 占位符:
_:单个任意字符
%:多个任意字符
select last_name from employees where last_name like '__e_a%'; // (第3个字符为e,第5个为a)
select last_name from employees where last_name like '_$_%' escape '$'; //(第2个字符为_ ,escape '$' 声明$为转义字符)
面试题:
Select * from employees;和Selcet * from employees where commission_pct like ‘%%’and last_name like ‘%%’;结果是否一样?并说明原因
答:结果不一样 ,因为表中可能存在NULL值,如果表中没有NULL值,则结果是一样的,若and改为or,则结果一样。
-------------------------------------------------------------------------
between and
select * from employees where salary between 100 and 120;//(100和120不能交换位置)
等价于
select * from employees where salary >= 100 and salary <= 120;
-------------------------------------------------------------------------
in
select * from employees where job_id in (100 ,120 ,130);
等价于
select * from employees where job_id = 100 or job_id = 110 or job_id = 130;
*注意:in列表的值类型必须统一或兼容
-------------------------------------------------------------------------
is null
is not null
select * from employees where salary is null;
select * from employees where salary is not null;
*注意:<=> 安全等于既能判断普通数值,又能判断null值
3. 常见函数
概念:类似于java的方法,将一组逻辑语句封装在方法体中,对外暴露方法名
好处:隐藏了实现细节,提高代码的重用性
调用: select 函数名(实参列表)【from表】;
分类:
(1)单行函数
如concat、 length、 ifnull等
(2)分组函数
功能:做统计使用,又称为统计函数、聚合函数、组函数
count:计算非空个数
max:计算最大值
min:计算最小值
sum:计算和
avg:计算平均值
(3)字符函数
concat: 拼接
select concat (last_name, '_',first_name) 姓名 from employees;
substr: 截取子串
select substr(‘123456’,4) out_put; //456 (索引从1开始)
select substr(‘你好世界’,1,3) out_put; //你好世,3代表截取长度
upper/ucase: 转换成大写
lower/lcase: 转换成小写
trim: 去前后指定的空格和字符
select length (trim (‘ 张翠山 ’));//3
select trim (‘a’ from ‘aaaaaaa张aaaaaaaa翠山aaaaaaaaaaaaa’); //张aaaaaaaa翠山
ltrim: 去左边空格
rtrim: 去右边空格
replace: 替
select repalce (’你好世界‘,’世界‘,’world‘) //你好world
lpad: 用指定的字符左填充指定长度
select lpad(‘殷素素’,2 ,‘*’); //殷素
rpad: 用指定的字符右填充指定长度
select rpad(‘殷素素’,12 ,‘ab‘); //殷素素ababababa
instr: 返回子串第一次出现的索引(找不到返回0)
length: 获取字节个数
(2)数学函数
round: 四舍五入
select round (-1.55);// -2
select round (1.567,2);//1.57 ,小数点后保留2位
rand: 随机数
floor: 向下取整
ceil/ceiling: 向上取整
mod: 取余
select mod (-10,-3)//-1 a-a/b*b
truncate: 截断
select truncate (1.65,1)//1.6 ,小数点后保留1位
(3)日期函数
now: 当前系统日期+时间
curdate: 当前系统日期
curtime: 当前系统时间
#可以获取指定的部分:年、月、日、小时、分钟、秒
SELECT YEAR(NOW( ))年;
SELECT YEAR ( '1998-1-1')年;
SELECT YEAR(hiredate)年FROM employees;
SELECT MONTH(NOW())月;
SELECT MONTHNAME(NOW())月; //显示为英文
(4)加密和系统函数
(5)流程控制函数
if 处理双分支
select if (10<5,'大','小')
case语句 处理多分支
语法:case要判新的字段或表达式
when常量1 then要显示的值1或语句1;
when常量2 then要显示的值2或语句2;
...
else 要显示的值n或语句n
end
情况1:处理等值判断
SELECT salary原始工资,department_id,
CASE department_id
WHEN 30 THEN salary* 1.1
WHEN 40 THEN salary*1.2
WHEN 50 THEN salary*1.3
ELSE salary
END AS 新工资
FROM employees;
情况2:处理条件判断
SELECT salary,
CASE
WHEN salary>20000 THEN "A"
WHEN salary>15000 THEN'B
WHEN salary>10000 THEN 'c'
ELSE 'D'
END As 工资级别 FROM employees;
(5)其他函数
version: 版本
database: 当前库
user: 当前连接用户
4. 分组函数
* count:计算非空个数
* 一般选择非空的列:主键
* count(*)
* max:计算最大值
* min:计算最小值
* sum:计算和
* avg:计算平均值
* 特点:
a. 以上五个分组函数都忽略null值,除了 count(*)
b. sum和avg一般用于处理数值型,max、min、count可以处理任何数据类型
c. 都可以搭配distinct使用,用于统计去重后的结果
d. count的参数可以支持:
字段、*、常量值(一般放1)
效率:
MYISAM存储引擎下, COUNT(*)的效率高
INNODB存储引擎下,COUNT(*)和COUNT(1)的效率差不多,比COUNT(字段)要高一些
—般使用count (*)用作统计行数
* 注意:聚合函数的计算,排除null值(否则null + 任何数据都为null)。
解决方案:
* 选择不包含非空的列进行计算
* IFNULL函数
IFNULL(表达式1,表达式2):null参与的运算,计算结果都为null
* 表达式1:哪个字段需要判断是否为null
* 表达式2: 如果该字段为null后的替换值。
5. 分组查询
* 语法:
select 查询的字段,分组函数
from 表
[where 筛选条件]
group by 分组的字段
[having 筛选条件]
注意:分组函数做条件肯定是放在having子句中
能用分组前筛选的,就优先考虑使用分组前筛选
* 特点:
(1)可以按单个字段分组
(2)和分组函数一同查询的字段最好是分组后的字段
(3)可以按表达式或函数分组
(3)可以按多个字段分组,字段之间用逗号隔开
(4)可以支持排序
(5)having后可以支持别名
* 面试相关
* where 和 having 的区别?
(1)where 在分组之前进行限定(数据源为原始表),如果不满足条件,则不参与分组。having在分组之后进行限定(数据源为分组后的结果集),如果不满足结果,则不会被查询出来
(2) where 后不可以跟聚合函数,having可以进行聚合函数的判断。
6. 排序查询
* 语法:
select
要查询的东西
from
表
【 where
条件 】
order by 排序的字段 | 表达式 | 函数 | 别名 【asc | desc】
* 排序方式:
* ASC:升序,默认的
* DESC:降序
*排序分类:
1.按单个字段进行排序
2.按多个字段排序
3.按表达式排序
4.按别名排序
5.按函数排序
* 注意:
* 如果有多个排序条件,则当之前的条件值一样时,才会判断第二条件
*order by 字句一般放在查询语句的最后面,limit子句除外
7. 分页查询
* 语法:
select 字段|表达式,...
from 表
where 条件
group by 分组字段
having 条件
order by 排序的字段
limit 起始的条目索引,条目数;
* 示例:每页显示3条记录
* SELECT * FROM student LIMIT 0,3; -- 第1页
* SELECT * FROM student LIMIT 3,3; -- 第2页
* SELECT * FROM student LIMIT 6,3; -- 第3页
* 特点:
a.起始条目索引从0开始
b.limit子句放在查询语句的最后
c.公式:select * from 表 limit (page-1)*sizePerPage,sizePerPage
假如:
每页显示条目数sizePerPage
要显示的页数 page
8. 多表连接查询
分类:
按年代分类:sql92标准(mysql中仅支持内连接)
sql99标准【推荐】
按功能分类:
内连接:
等值连接
非等值连接
自连接
外连接:
左外连接
右外连接
全外连接
交叉连接
(1)笛卡尔集
* 产生条件:
a. 省略连接条件
b. 连接条件无效
c. 所有表中所有行互相连接
* 解决方案:
添加有效筛选条件
(2) 内连接
* SQL92语法:
SELECT 查询列表
FROM 表名1 别名1 ,表名2 别名2
WHERE 连接条件
AND 筛选条件
GROUP BY 分组列表
HAVING 分组后筛选条件
ORDER BY 排序列表
* SQL99语法:
select 字段列表
from 表名1
[inner] join 表名2 on 条件
where 筛选条件
group by 分组条件
having 分组后的筛选条件
order by 排序字段
a. 等值连接
SELECT last_name , department_name
FROM employees e
INNER JOIN departments d
ON e.'department_id` = d. 'department_id`;
b.非等值连接
SELECT COUNT (*),grade level
FROM employees e
JOIN job_grades g
ON e.'salary BETWEEN g.`lowest_sal’ AND g.'highest_sal`
GROUP BY grade_level
HAVING COUNT(*)>20
ORDERBY grade level DESC;
c.自连接
SELECT e.last name, m.last name
FROM employees e
JOIN employees m
ON e."manager_id T= m."employee_ id`
WHERE e.last_name` LIKE '%k%';
* 注意:
a. 使用表名前缀在多个表中区分相同的列
b. 在不同表中具有相同列名的列可以用表的别名加以区分
c. 如果使用了表别名,则在select语句中需要使用表别名代替表名
d. 表别名最多支持32个字符长度,但建议越少越好
(3)外连接
应用场景:用于查询一个表有,另一个表没有的记录
特点:
a. 外连接的查询结果为主表中的所有记录
如果从表中有和它匹配的,则显示匹配的值如果从表中没有和它匹配的,则显示null
外连接查询结果=内连接结果+主表中有而从表没有的记录
b. 左外连接,left join左边的是主表右外连接,right join右边的是主表
c. 左外和右外交换两个表的顺序,可以实现同样的效果
d. 全外连接=内连接的结果+表1中有但表2没有的+表2中有但表1没有的
a. 左外连接
* 语法:
select 字段列表
from 表1
left [outer] join 表2 on 条件
...
* 注意:
左外连接查询的是左表所有数据以及其交集部分
SELECT b.name
FROM beauty b
LEFT OUTER JOIN boys bo
ON b.`boyfriend_id` = bo.`id`
WHERE bo.`id` IS NULL;
b. 右外连接
* 语法:
select 字段列表
from 表1
right [outer] join 表2 on 条件
...
* 注意:
右外连接查询的是右表所有数据以及其交集部分
SELECT d.* ,e.employee_idFROM employees e
RIGHT OUTERJOIN departments d
oN d. 'department_id` = e.`department_id`WHERE e. ' employee_id`IS NULL;
c.全外连接
USE girls;
SELECT b.* ,bo .*
FROM beauty b
FULL OUTER JOIN boys bo
ON b. `boyfriend_id` = bo.id;
(4)交叉连接
即笛卡尔集
SELECT b.*,bo .*
FROM beauty b
CROSS JOIN boys bo;
(5)子查询
含义:出现在其他语句中的select语句,称为子查询或内查询外部的查询语句,称为主查询或外查询
概念:查询中嵌套查询,称嵌套查询为子查询
分类:
按子查询出现的位置:
select后面:
仅仅支持标量子查询
from后面:
支持表子查询
where或having后面:
标量子查询
列子查询
行子查询
exists后面(相关子查询)
表子查询
按结果集的行列数不同:
标量子查询(结果集只有一行一列)
列子查询(结果集只有一列多行)
行子查询(结果集有一行多列)
表子查询(结果集—般为多行多列)
* 特点:
a.子查询都放在小括号内
b.子查询可以放在from后面、select后面、where后面、having后面,但一般放在条件的右侧
c.子查询优先于主查询执行,主查询使用了子查询的执行结果
d.子查询根据查询结果的行数不同分为以下两类:
① 单行子查询
结果集只有一行
一般搭配单行操作符使用:> < = <> >= <=
非法使用子查询的情况:
a、子查询的结果为一组值
b、子查询的结果为空
② 多行子查询
结果集有多行
一般搭配多行操作符使用:any/some、all、in、not in
in: 属于子查询结果中的任意一个就行
any和all往往可以用其他查询代替
SELECTlast_name FROM employees
WHERE department_id IN(
SELECT DISTINCT department_id FROM departments
WHERE location_id IN(1400,1700)
SELECT last_name, employee_id,job_id,salaryFROM employees
WHERE salary < ANY(
SELECT DISTINCT salary FROM employees
WHERE job_id = 'IT_PROG'
AND job_id <> 'IT_PROG' ;
//行子查询
SELECT*
FROM employees
WHERE( employee_id, salary)=(
SELECT MIN( employee_id) ,MAX( salary)FROM employees)
exists后面(相关子查询) (判断是否存在,结果1或0)
SELECT EXISTS (SELECT employee_id FROM employees); //1
SELECT department_name
FROM departments d
WHERE EXISTS(
SELECT*
FROM employees e
WHERE d.`department_id'=e.'department_id`
(6)联合查询(union )
* 语法:
select 字段|常量|表达式|函数 from 表 where 条件 union 【all】
select 字段|常量|表达式|函数 from 表 where 条件 union 【all】
select 字段|常量|表达式|函数 from 表 where 条件 union 【all】
.....
select 字段|常量|表达式|函数 from 表 where 条件
* 特点:
1、多条查询语句的查询的列数必须是一致的
2、多条查询语句的查询的列的类型几乎相同
3、union代表去重,union all代表不去重
SELECT * FROM employees WHERE email LIKE '%a%' OR department_id>90 ;
--拆分为
SELECT *FROM employees WHERE email LIKE '%a%'
UNION
SELECT *FROM employees WHERE department_id>90;
四、 DML 语言(数据操纵语言)
1. 添加数据:
* 语法:
方式一: insert into 表名(列名1,列名2,...列名n) values(值1,值2,...值n);
特点:支持插入多行,支持子查询(可以直接将查询结果插入)
INSERT INTO beauty
VALUES (23,'唐艺昕1','女','1990-4-23','1898888888',NULL,2),
(24,'唐艺昕2','女','1990-4-23','1898888888 ',NULL,2),
(25,'唐艺昕3','女','1990-4-23', '1898888888',NULL,2);
INSERT INTO beauty (id,NAME, phone)
SELECT id, boyname, ' 11809866'
FROM boys WHERE id<3;
方式二: insert into 表名 set 列名 = 值,列名 = 值 ,... ;
* 注意:
(1)列名和值要一一对应。
(2)如果表名后,不定义列名,则默认给所有列添加值
insert into 表名 values(值1,值2,...值n);
(3)除了数字类型,其他类型需要使用引号(单双都可以)引起来
#说明 insert 语句的细节
-- 1.插入的数据应与字段的数据类型相同。
-- 比如 把 'abc' 添加到 int 类型会错误
INSERT INTO `goods` (id, goods_name, price)
VALUES('韩顺平', '小米手机', 2000);
-- 2. 数据的长度应在列的规定范围内,例如:不能将一个长度为 80 的字符串加入到长度为 40 的列中。
INSERT INTO `goods` (id, goods_name, price)
VALUES(40, 'vovo 手机 vovo 手机 vovo 手机 vovo 手机 vovo 手机', 3000);
-- 3. 在 values 中列出的数据位置必须与被加入的列的排列位置相对应。
INSERT INTO `goods` (id, goods_name, price) -- 不对
VALUES('vovo 手机',40, 2000);
-- 4. 字符和日期型数据应包含在单引号中。
INSERT INTO `goods` (id, goods_name, price)
VALUES(40, vovo 手机, 3000); -- 错误的 vovo 手机 应该 'vovo 手机'
-- 5. 列可以插入空值[前提是该字段允许为空],insert into table value(null)
INSERT INTO `goods` (id, goods_name, price)
VALUES(40, 'vovo 手机', NULL);
-- 6. insert into tab_name (列名..) values (),(),() 形式添加多条记录
INSERT INTO `goods` (id, goods_name, price)
VALUES(50, '三星手机', 2300),(60, '海尔手机', 1800);
-- 7. 如果是给表中的所有字段添加数据,可以不写前面的字段名称
INSERT INTO `goods` VALUES(70, 'IBM 手机', 5000);
-- 8. 默认值的使用,当不给某个字段值时,如果有默认值就会添加默认值,否则报错
-- 如果某个列 没有指定 not null ,那么当添加数据时,没有给定值,则会默认给 null -- 如果我们希望指定某个列的默认值,可以在创建表时指定
INSERT INTO `goods` (id, goods_name)
VALUES(80, '格力手机');
SELECT * FROM goods;
INSERT INTO `goods2` (id, goods_name)
VALUES(10, '顺平手机');
SELECT * FROM goods2;
-------------------------------------------------------------------------
2. 修改数据:
* 语法:
* 修改单表: update 表名 set 列名1 = 值1, 列名2 = 值2,... [where 条件];
* 修改多表: update 表1 别名1,表2 别名2 set 字段=新值,字段=新值 where 连接条件 and 筛选条件
UPDATE boys bo
INNER JOIN beauty b ON bo.'id '= b.'boyfriend_id
SET b.'phone `='114'
WHERE bo.'boyName`='张无忌';
* 注意:
1. 如果不加任何条件,则会将表中所有记录全部修改
-------------------------------------------------------------------------
3. 删除数据:
* 语法:
方式一:
(1)单表的删除
delete from表名 【where筛选条件】
(2)多表的删除【补充】
sql92语法:
delete 表1的别名,表2的别名 from 表1 别名,表2 别名
where连接条件
and筛选条件;
sql99语法:
delete表1的别名,表2的别名
from表1别名
inner | left l right join 表2 别名 on 连接条件
where 筛选条件;
DELETE b
FROM beauty b
INNER JOIN boys bo ON b. 'boyfriend_id` = bo. 'id
WHERE bo . `boyName '=张无忌';
方式二:
truncate table 表名;--清空数据
* 注意:
(1)如果不加条件,则删除表中所有记录。
(2)如果要删除所有记录
a. delete from 表名; -- 不推荐使用。有多少条记录就会执行多少次删除操作
b. TRUNCATE TABLE 表名; -- 推荐使用,效率更高 先删除表,然后再创建一张一样的表。
* 面试题:delete与TRUNCATE区别?
(1)truncate不能加where条件,而delete可以加where条件
(2)truncate的效率高
(3)truncate 删除带自增长的列的表后,如果再插入数据,数据从1开始
(4)delete 删除带自增长列的表后,如果再插入数据,数据从上一次的断点处开始
(5)truncate删除不能回滚,delete删除可以回滚
4. 表复制
-- 表的复制
-- 为了对某个 sql 语句进行效率测试,我们需要海量数据时,可以使用此法为表创建海量数据
CREATE TABLE my_tab01
( id INT, `name` VARCHAR(32), sal DOUBLE, job VARCHAR(32), deptno INT);
DESC my_tab01
SELECT * FROM my_tab01; -- 演示如何自我复制
-- 1. 先把 emp 表的记录复制到 my_tab01
INSERT INTO my_tab01
(id, `name`, sal, job,deptno)
SELECT empno, ename, sal, job, deptno FROM emp;
-- 2. 自我复制
INSERT INTO my_tab01
SELECT * FROM my_tab01;
SELECT COUNT(*) FROM my_tab01;
-- 如何删除掉一张表重复记录
-- 1. 先创建一张表 my_tab02, -- 2. 让 my_tab02 有重复的记录
CREATE TABLE my_tab02 LIKE emp; -- 这个语句 把 emp 表的结构(列),复制到 my_tab02
DESC my_tab02;
INSERT INTO my_tab02
SELECT * FROM emp;
SELECT * FROM my_tab02; -- 3. 考虑去重 my_tab02 的记录
/*
思路
(1) 先创建一张临时表 my_tmp , 该表的结构和 my_tab02 一样
(2) 把 my_tmp 的记录 通过 distinct 关键字 处理后 把记录复制到 my_tmp
(3) 清除掉 my_tab02 记录
(4) 把 my_tmp 表的记录复制到 my_tab02
(5) drop 掉 临时表 my_tmp
*/ -- (1) 先创建一张临时表 my_tmp , 该表的结构和 my_tab02 一样
create table my_tmp like my_tab02
-- (2) 把 my_tmp 的记录 通过 distinct 关键字 处理后 把记录复制到 my_tmp
insert into my_tmp
select distinct * from my_tab02;
-- (3) 清除掉 my_tab02 记录
delete from my_tab02; -- (4) 把 my_tmp 表的记录复制到 my_tab02
insert into my_tab02
select * from my_tmp; -- (5) drop 掉 临时表 my_tmp
drop table my_tmp;
select * from my_tab02;
五、 DDL语言(数据定义语言)
1. 数据库操作
* 创建数据库:
* create database 数据库名称;
* 创建数据库,判断不存在,再创建:
* create database if not exists 数据库名称;
* 创建数据库,并指定字符集
* create database 数据库名称 character set 字符集名;
#创建一个使用 utf8 字符集,并带校对规则的 hsp_db03 数据库
CREATE DATABASE hsp_db03 CHARACTER SET utf8 COLLATE utf8_bin
#校对规则 utf8_bin 区分大小 默认 utf8_general_ci 不区分大小写
#备份, 要在 Dos 下执行 mysqldump 指令其实在 mysql 安装目录\bin
#这个备份的文件,就是对应的 sql 语句
mysqldump -u root -p -B hsp_db02 hsp_db03 > d:\\bak.sql
DROP DATABASE ecshop;
#恢复数据库(注意:进入 Mysql 命令行再执行)
source d:\\bak.sql
#第二个恢复方法, 直接将 bak.sql 的内容放到查询编辑器中,执行
-------------------------------------------------------------------------
* 查询所有数据库的名称:
* show databases;
* 查询某个数据库的字符集:查询某个数据库的创建语句
* show create database 数据库名称;
-------------------------------------------------------------------------
*修改数据库的字符集
* alter database 数据库名称 character set 字符集名称;
-------------------------------------------------------------------------
* 删除数据库
* drop database 数据库名称;
* 判断数据库存在,存在再删除
* drop database if exists 数据库名称;
-------------------------------------------------------------------------
* 查询当前正在使用的数据库名称
* select database();
* 使用数据库
* use 数据库名称;
2. 数据表操作
* 表的创建
* create table 表名(
列名1 数据类型1 【字段约束】,
列名2 数据类型2 【字段约束】,
....
列名n 数据类型n 【字段约束】
);
* 注意:最后一列,不需要加逗号(,)
CREATE TABLE `user` (
id INT, `name` VARCHAR(255), `password` VARCHAR(255), `birthday` DATE)
CHARACTER SET utf8 COLLATE utf8_bin ENGINE INNODB;
-------------------------------------------------------------------------
* 查询当前数据库中所有的表
* show tables;
* 查询某个数据库中所有的表
* show tables from 数据库名称;
* 查询表结构
* desc 表名;
-------------------------------------------------------------------------
* 修改表名
* alter table 表名 rename to 新的表名;
* 修改表的字符集
* alter table 表名 character set 字符集名称;
* 添加一列
* alter table 表名 add [column] 列名 数据类型;
* 修改列名称 类型
* alter table 表名 change [column] 列名 新列名 新数据类型;
* alter table 表名 modify [column] 列名 新数据类型;
* 删除列
* alter table 表名 drop [column] 列名;
-------------------------------------------------------------------------
* 删除表
* drop table 表名;
* drop table if exists 表名;
3. MySQL常用数据类型
(1)整数类型
#1. 如果没有指定 unsinged , 则 TINYINT 就是有符号
#2. 如果指定 unsinged , 则 TINYINT 就是无符号 0-255
CREATE TABLE t3 (
id TINYINT);
CREATE TABLE t4 (
id TINYINT UNSIGNED);
INSERT INTO t3 VALUES(127); #这是非常简单的添加语句
SELECT * FROM t3
INSERT INTO t4 VALUES(255);
SELECT * FROM t4;
数值型(bit)的使用
(2) 小数类型
(3)字符串
#演示字符串类型使用 char varchar
#注释的快捷键 shift+ctrl+c , 注销注释 shift+ctrl+r
-- CHAR(size)
-- 固定长度字符串 最大 255 字符
-- VARCHAR(size) 0~65535 字节
-- 可变长度字符串 最大 65532 字节 【utf8 编码最大 21844 字符 1-3 个字节用于记录大小】
-- 如果表的编码是 utf8 varchar(size) size = (65535-3) / 3 = 21844
-- 如果表的编码是 gbk varchar(size) size = (65535-3) / 2 = 32766
CREATE TABLE t09 (
`name` CHAR(255));
CREATE TABLE t10 (
`name` VARCHAR(32766)) CHARSET gbk;
DROP TABLE t10;
(3)date:日期,只包含年月日,yyyy-MM-dd
(4)datetime:日期,包含年月日时分秒 yyyy-MM-dd HH:mm:ss
(5)timestamp:时间戳类型 包含年月日时分秒 yyyy-MM-dd HH:mm:ss
如果将来不给这个字段赋值,或赋值为null,则默认使用当前的系统时间,来自动赋值
(6) varchar:字符串
name varchar(20):姓名最大20个字符
zhangsan 8个字符 张三 2个字符
4. 约束
* 概念: 对表中的数据进行限定,保证数据的正确性、有效性和完整性。
* 分类:
(1)主键约束:primary key
(2)非空约束:not null
(3)唯一约束:unique
(4)外键约束:foreign key
(5)默认约束:default(设置默认值)
-------------------------------------------------------------------------
* 非空约束:not null,某一列的值不能为null
(1)创建表时添加约束
CREATE TABLE stu(
id INT,
NAME VARCHAR(20) NOT NULL -- name为非空);
(2) 创建表完后,添加非空约束
ALTER TABLE stu MODIFY NAME VARCHAR(20) NOT NULL;
(3) 删除name的非空约束
ALTER TABLE stu MODIFY NAME VARCHAR(20);
-------------------------------------------------------------------------
* 唯一约束:unique,某一列的值不能重复
(1) 注意:
* 唯一约束可以有NULL值,但是只能有一条记录为null
(2) 在创建表时,添加唯一约束
CREATE TABLE stu(
id INT,
phone_number VARCHAR(20) UNIQUE -- 手机号);
(3) 删除唯一约束
ALTER TABLE stu DROP INDEX phone_number;
(4) 在表创建完后,添加唯一约束
ALTER TABLE stu MODIFY phone_number VARCHAR(20) UNIQUE;
-------------------------------------------------------------------------
* 主键约束:primary key
(1) 注意:
a. 含义:非空且唯一
b. 一张表只能有一个字段为主键
c. 主键就是表中记录的唯一标识
(2) 在创建表时,添加主键约束
create table stu(
id int primary key,-- 给id添加主键约束
name varchar(20));
(3) 删除主键
-- 错误 alter table stu modify id int ;
ALTER TABLE stu DROP PRIMARY KEY;
(4) 创建完表后,添加主键
ALTER TABLE stu MODIFY id INT PRIMARY KEY;
(5) 自动增长:
a. 概念:如果某一列是数值类型的,使用 auto_increment 可以来完成值的自动增长
b. 在创建表时,添加主键约束,并且完成主键自增长
create table stu(
id int primary key auto_increment,-- 给id添加主键约束
name varchar(20));
c. 删除自动增长
ALTER TABLE stu MODIFY id INT;
d. 添加自动增长
ALTER TABLE stu MODIFY id INT AUTO_INCREMENT;
-------------------------------------------------------------------------
* 外键约束:foreign key,让表与表产生关系,从而保证数据的正确性。
(1) 在创建表时,可以添加外键
* 语法:
create table 表名(
....
外键列
constraint 外键名称 foreign key (外键列名称) references 主表名称(主表列名称));
(2) 删除外键
ALTER TABLE 表名 DROP FOREIGN KEY 外键名称;
(3) 创建表之后,添加外键
ALTER TABLE 表名 ADD CONSTRAINT 外键名称 FOREIGN KEY (外键字段名称) REFERENCES 主表名称(主表列名称);
(4) 级联操作
a. 添加级联操作
语法:ALTER TABLE 表名 ADD CONSTRAINT 外键名称
FOREIGN KEY (外键字段名称) REFERENCES 主表名称(主表列名称) ON UPDATE CASCADE ON DELETE CASCADE ;
b. 分类:
①级联更新:ON UPDATE CASCADE
② 级联删除:ON DELETE CASCADE
-------------------------------------------------------------------------
* check约束:
六、TCL语言(事务控制语言)
1. 事务
(1)概念
* 如果一个包含多个步骤的业务操作,被事务管理,那么这些操作要么同时成功,要么同时失败。
(2)事务和锁
回退事务
提交事务
-- 事务的一个重要的概念和具体操作
-- 看一个图[看示意图]
-- 演示
-- 1. 创建一张测试表
CREATE TABLE t27
( id INT, `name` VARCHAR(32)); -- 2. 开始事务
START TRANSACTION
-- 3. 设置保存点
SAVEPOINT a
-- 执行 dml 操作
INSERT INTO t27 VALUES(100, 'tom');
SELECT * FROM t27;
SAVEPOINT b
-- 执行 dml 操作
INSERT INTO t27 VALUES(200, 'jack');
-- 回退到 b
ROLLBACK TO b
-- 继续回退 a
ROLLBACK TO a
-- 如果这样, 表示直接回退到事务开始的状态. ROLLBACK
COMMIT
事务细节
-- 1. 如果不开始事务,默认情况下,dml 操作是自动提交的,不能回滚
INSERT INTO t27 VALUES(300, 'milan'); -- 自动提交 commit
SELECT * FROM t27
-- 2. 如果开始一个事务,你没有创建保存点. 你可以执行 rollback,
-- 默认就是回退到你事务开始的状态
START TRANSACTION
INSERT INTO t27 VALUES(400, 'king');
INSERT INTO t27 VALUES(500, 'scott');
ROLLBACK -- 表示直接回退到事务开始的的状态
COMMIT;
-- 3. 你也可以在这个事务中(还没有提交时), 创建多个保存点.
比如: savepoint aaa; -- 执行 dml , savepoint bbb
-- 4. 你可以在事务没有提交前,选择回退到哪个保存点
-- 5. InnoDB 存储引擎支持事务 , MyISAM 不支持
-- 6. 开始一个事务 start transaction, set autocommit=off
(3)事务的隔离级别(面试常考)
a. * 事务并发问题是如何产生的?
当多个事务同时操作同一个数据库的相同数据时
* 事务并发问题
-脏读:一个事务读取到了另外一个事务未提交的数据
- 不可重复读:一个事务先后执行同一条 SQL,由于其他提交事物所做的修改,导致两次读取到的数据不同,就是不可重复读。
- 幻读:一个事务读取数据时,另外一个事务提交了插入、删除或修改操作,但是第一个事务读取不到已经更新后的数据
(①另一个事物提交了增加操作,当前事物查询不到新增的这条数据,但是这条数据实际已经存在,当前事物可以对其进行操作。②另一个事物提交了删除操作,当前事物依然查询到了已经删除的这条数据,但是这条数据实际已经不存在,当前事物已经不能对其进行操作。③另一个事物提交了修改操作,当前事物查询到的依然是被修改之前的数据,但是这条数据实际已经被更改,当前事物再对其进行同样值的修改操作时,影响行数为0,修改不成功)。
脏读和不可重复读的区别:
脏读可以读到其他事务中未提交的数据,
而不可重复读是读取到了其他事务已经提交的数据,但前后两次读取的结果不同。
不可重复读和幻读的区别:
不可重复读描述的侧重点是修改操作,
而幻读描述的侧重点是添加和删除操作。
b . 事物隔离级别
c.* 处理事务并发问题,设置事务隔离级别
设置事务隔离级别
1. 开了两个 mysql 的控制台
-- 2. 查看当前 mysql 的隔离级别
SELECT @@tx_isolation; -- mysql> SELECT @@tx_isolation; -- +-----------------+
-- | @@tx_isolation | -- +-----------------+
-- | REPEATABLE-READ | -- +-----------------+
-- 3.把其中一个控制台的隔离级别设置 Read uncommitted
SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED
-- 4. 创建表
CREATE TABLE `account`(
id INT, `name` VARCHAR(32), money INT);
-- 查看当前会话隔离级别
SELECT @@tx_isolation
-- 查看系统当前隔离级别
SELECT @@global.tx_isolation
-- 设置当前会话隔离级别
SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED
-- 设置系统当前隔离级别
SET GLOBAL TRANSACTION ISOLATION LEVEL [你设置的级别]
(4)事务的ACID特征
* 原子性(Atomicity):是不可分割的最小操作单位,要么同时成功,要么同时失败
* 一致性(Consistency):保证数据的状态操作前和操作后保持一致
* 隔离性(Isolation):多个事务同时操作相同数据库的同一个数据时,一个事务的执行不受另外一个事务的干扰
* 持久性(Durability):当事务提交或回滚后,数据库会持久化的保存数据
(5)事务分类
* 隐式事务:没有明显的开启和结束事务的标志
* insert、update、delete语句本身就是一个事务
* 显式事务:具有明显的开启和结束事务的标志
a. 取消自动提交事务:set autocommit=0;
b. 开启事务:start transaction;
c. 提交或回滚事务:
- commit;
- rollback;
(6)数据库引擎
主要的存储引擎/表类型特点
细节说明
-- 表类型和存储引擎
-- 查看所有的存储引擎
SHOW ENGINES
-- innodb 存储引擎,是前面使用过. -- 1. 支持事务 2. 支持外键 3. 支持行级锁
START TRANSACTION;
SAVEPOINT t1
INSERT INTO t28 VALUES(1, 'jack');
SELECT * FROM t28;
ROLLBACK TO t1
-- myisam 存储引擎 -- 1. 添加速度快 2. 不支持外键和事务 3. 支持表级锁
CREATE TABLE t28 (
id INT, `name` VARCHAR(32)) ENGINE MYISAM
-- memory 存储引擎
-- 1. 数据存储在内存中[关闭了 Mysql 服务,数据丢失, 但是表结构还在]
-- 2. 执行速度很快(没有 IO 读写) 3. 默认支持索引(hash 表)
CREATE TABLE t29 (
id INT, `name` VARCHAR(32)) ENGINE MEMORY
DESC t29
INSERT INTO t29
VALUES(1,'tom'), (2,'jack'), (3, 'hsp');
SELECT * FROM t29
-- 指令修改存储引擎
ALTER TABLE `t29` ENGINE = INNODB
如何选择表的存储引擎
![1e07e6c3cb6749ddb4151cd5bcaece85.png](https://i-blog.csdnimg.cn/blog_migrate/4439328e67c9b7ccdc79ebef0ba4fe03.png)
修改存储引擎
* 面试题:MyISAM 与 InnoDB 区别?
2. 视图
含义:一张虚拟的表
好处:
-
sql语句提高重用性,效率高
-
和表实现了分离,提高了安全性
视图的基本使用
-------------------------------------------------------------------------
* 视图创建
* 语法
CREATE VIEW 视图名
AS 查询语句;
* 示例
CREATE VIEW myview as select * from user;
-------------------------------------------------------------------------
* 视图更新
* 语法
- CREATE OR REPLACE VIEW 视图名
AS 查询语句;
- ALTER VIEW 视图名
AS 查询语句;
* 示例
- CREATE OR REPLACE VIEW myview
AS SELECT name FROM employees
WHERE employee_id>100;
- ALTER VIEW myview
AS SELECT employee_id FROM employees;
* 注意:视图的可更新性和视图中查询的定义有关系,以下类型的视图是不能更新的
- 包含以下关键字的sql语句:分组函数、distinct、group by、having、union或者union all
- 常量视图
- Select中包含子查询
- join
- from一个不能更新的视图
- where子句的子查询引用了from子句中的表
-------------------------------------------------------------------------
* 视图删除
* 语法
DROP VIEW 视图名1,视图名2...;
* 示例
DROP VIEW test_v1,test_v2,test_v3;
-------------------------------------------------------------------------
* 视图结构查看
* 语法
- DESC 视图名;
- SHOW CREATE VIEW 视图名;
* 示例
- DESC test_v7;
- SHOW CREATE VIEW test_v7;
-------------------------------------------------------------------------
* 查看视图数据
* 语法
SELECT 查询字段
FROM 视图名;
* 示例
SELECT * FROM myview WHERE name='Partners';
-------------------------------------------------------------------------
* 插入视图数据
* 语法
INSERT INTO 视图名(视图字段)
VALUES(值)
* 示例
INSERT INTO myview(name,age) VALUES('虚竹',90);
-------------------------------------------------------------------------
* 修改视图数据
* 语法
UPDATE 视图名
SET 视图字段名=值
WHERE 条件
* 示例
UPDATE myview SET name ='梦姑' WHERE name='虚竹';
-------------------------------------------------------------------------
*删除视图数据
* 语法
DELETE FROM 视图名
WHERE 条件;
* 示例
DELETE FROM myview;
-------------------------------------------------------------------------
面试题
视图与表的区别? 使用方式 占用物理空间
视图 完全相同 不占用,仅仅保存的是SQL逻辑
表 完全相同 占用
3. 存储过程
含义:一组经过预先编译的sql语句的集合 好处:
-
提高了sql语句的重用性,减少了开发程序员的压力
-
提高了效率
-
减少了传输次数
分类:
-
无返回无参
-
仅仅带in类型,无返回有参
-
仅仅带out类型,有返回无参
-
既带in又带out,有返回有参
-
带inout,有返回有参
注意:in、out、inout都可以在一个存储过程中带多个
-------------------------------------------------------------------------
创建存储过程
* 语法 create procedure 存储过程名(in|out|inout 参数名 参数类型,...) begin 存储过程体 end
类似于方法:
修饰符 返回类型 方法名(参数类型 参数名,...){ 方法体; }
注意:
a.需要设置新的结束标记 delimiter 新的结束标记 示例: delimiter $ CREATE PROCEDURE 存储过程名(IN|OUT|INOUT 参数名 参数类型,...) BEGIN sql语句1; sql语句2; END $ b.存储过程体中可以有多条sql语句,如果仅仅一条sql语句,则可以省略begin end c.参数前面的符号的意思 - in:该参数只能作为输入 (该参数不能做返回值) - out:该参数只能作为输出(该参数只能做返回值) - inout:既能做输入又能做输出
-------------------------------------------------------------------------
调用存储过程
* 语法 call 存储过程名(实参列表)
-------------------------------------------------------------------------
删除存储过程
* 语法 DROP PROCEDURE 存储过程名; * 注意:不能同时删除多个存储过程
-------------------------------------------------------------------------
查看存储过程结构
* 语法 SHOW CREATE PROCEDURE 存储过程名;
-------------------------------------------------------------------------
4. 函数
含义:经过编译并存储在数据库中的一段sql语句的集合
-------------------------------------------------------------------------
创建函数
* 语法 CREATE FUNCTION 函数名(参数名 参数类型,...) RETURNS 返回类型 BEGIN 函数体 END
-------------------------------------------------------------------------
调用函数
* 语法 SELECT 函数名(实参列表)
-------------------------------------------------------------------------
查看函数结构
* 语法 SHOW CREATE FUNCTION 函数名;
-------------------------------------------------------------------------
删除函数
* 语法 DROP FUNCTION 函数名;
-------------------------------------------------------------------------
函数和存储过程的区别
关键字 调用语法 返回值 应用场景 函数 FUNCTION SELECT 函数() 只能是一个 一般用于查询结果为一个值并返回时,当有返回值而且仅仅一个 存储过程 PROCEDURE CALL 存储过程() 可以有0个或多个 一般用于更新
七、DCL语言(数据控制语言)Mysql 管理
1. Mysql 用户
2. 创建用户
3. 删除用户
4. 用户修改密码
5. mysql 中的权限
6. 给用户授权
7. 回收用户授权
8. 权限生效指令
9. 细节说明
八、 数据库设计
1. 多表之间的关系
(1)分类:
a. 一对一(了解):
* 如:人和身份证
* 分析:一个人只有一个身份证,一个身份证只能对应一个人
b. 一对多(多对一):
* 如:部门和员工
* 分析:一个部门有多个员工,一个员工只能对应一个部门
c. 多对多:
* 如:学生和课程
* 分析:一个学生可以选择很多门课程,一个课程也可以被很多学生选择
(2) 实现关系:
a. 一对多(多对一):
* 如:部门和员工
* 实现方式:在多的一方建立外键,指向一的一方的主键。
b. 多对多:
* 如:学生和课程
* 实现方式:多对多关系实现需要借助第三张中间表。中间表至少包含两个字段,这两个字段作为第三张表的外键,分别指向两张表的主键
c. 一对一(了解):
* 如:人和身份证
* 实现方式:一对一关系实现,可以在任意一方添加唯一外键指向另一方的主键。
(3)案例
-- 创建旅游线路分类表 tab_category
-- cid 旅游线路分类主键,自动增长
-- cname 旅游线路分类名称非空,唯一,字符串 100
CREATE TABLE tab_category (
cid INT PRIMARY KEY AUTO_INCREMENT,
cname VARCHAR(100) NOT NULL UNIQUE);
-- 创建旅游线路表 tab_route
/*
rid 旅游线路主键,自动增长
rname 旅游线路名称非空,唯一,字符串 100
price 价格
rdate 上架时间,日期类型
cid 外键,所属分类
*/
CREATE TABLE tab_route(
rid INT PRIMARY KEY AUTO_INCREMENT,
rname VARCHAR(100) NOT NULL UNIQUE,
price DOUBLE,
rdate DATE,
cid INT,
FOREIGN KEY (cid) REFERENCES tab_category(cid));
/*创建用户表 tab_user
uid 用户主键,自增长
username 用户名长度 100,唯一,非空
password 密码长度 30,非空
name 真实姓名长度 100
birthday 生日
sex 性别,定长字符串 1
telephone 手机号,字符串 11
email 邮箱,字符串长度 100
*/
CREATE TABLE tab_user (
uid INT PRIMARY KEY AUTO_INCREMENT,
username VARCHAR(100) UNIQUE NOT NULL,
PASSWORD VARCHAR(30) NOT NULL,
NAME VARCHAR(100),
birthday DATE,
sex CHAR(1) DEFAULT '男',
telephone VARCHAR(11),
email VARCHAR(100) );
/*
创建收藏表 tab_favorite
rid 旅游线路 id,外键
date 收藏时间
uid 用户 id,外键
rid 和 uid 不能重复,设置复合主键,同一个用户不能收藏同一个线路两次
*/
CREATE TABLE tab_favorite (
rid INT, -- 线路id
DATE DATETIME,
uid INT, -- 用户id
-- 创建复合主键
PRIMARY KEY(rid,uid), -- 联合主键
FOREIGN KEY (rid) REFERENCES tab_route(rid),
FOREIGN KEY(uid) REFERENCES tab_user(uid) );
九、MySQL索引
1. 索引的原理
2. 索引的类型
3. 索引使用
-- 1. 如果某列的值,是不会重复的,则优先考虑使用 unique 索引, 否则使用普通索引
-- 添加普通索引方式 2
ALTER TABLE t25 ADD INDEX id_index (id)
-- 添加主键索引
CREATE TABLE t26 (
id INT , `name` VARCHAR(32));
ALTER TABLE t26 ADD PRIMARY KEY (id)
SHOW INDEX FROM t25
-- 删除索引
DROP INDEX id_index ON t25
-- 删除主键索引
ALTER TABLE t26 DROP PRIMARY KEY
-- 修改索引 , 先删除,在添加新的索引
-- 查询索引
-- 1. 方式
SHOW INDEX FROM t25
-- 2. 方式
SHOW INDEXES FROM t25
-- 3. 方式
SHOW KEYS FROM t25
-- 4 方式
DESC t25
4. mysql索引失效情况
(1)没有使用索引列作为WHERE子句的查询条件。
(2)对索引列进行函数操作。比如字符串操作、日期操作等,MySQL将无法使用索引,此时索引失效。因为MySQL无法在运行时使用函数计算来匹配索引。
(3)对索引列进行类型转换。如果索引列是数字类型,但是你传入的值是字符串,那这个时候MysqI会默认对类型进行转化,同样会导致MySQL将无法使用索引,MySQL在使用索引时必须将查询条件与索引列的数据类型匹配。
(4)LIKE查询的查询字符串以通配符开头。当使用LIKE查询并且查询字符串以通配符
(例如%或_)开头时,MySQL无法使用索引,因为通配符在开头时无法进行前缀匹配。
(5)OR条件查询。当查询中包含OR条件时,如果OR条件中的每个条件都不涉及索引列,MySQL无法使用索引,此时索引失效。
(6)查询条件涉及到大量数据。当查询条件涉及到大量数据时,例如返回表中大部分数据的查询,MySQL可能会认为使用索引并不高效,因此会放弃使用索引。
十、SQL优化
1. 加索引,增加索引是一种简单高效的手段,但是需要选择合适的列,同时避免导致
索引失效的操作,比如like、函数等。
2.避免返回不必要的数据列,减少返回的数据列可以增加查询的效率。
3.根据查询分析器适当优化SQL的结构,比如是否走全表扫描、避免子查询等
4.分库分表,在单表数据量较大或者并发连接数过高的情况下,通过这种方式可以有
效提升查询效率
5.读写分离,针对读多写少的场景,这样可以保证写操作的数据库承受更小的压力,
也可以缓解独占锁和共享锁的竞争。