MySQL进阶

一 多表查询

多表查询操作,是在项目开发时使用较多的查询操作,这里以两张表的操作方式示例,更多表的操作再
次基础上拓展即可。

(一)多表关系

1 一对一

案例:
人和身份证号
奥运会比赛中,国家队与国家
一个国家只允许有一只国家队,一个国家队也只代表一个国家
用户和个人资料
方式1:通过修改表结构添加外键
修改表结构: ALTER TABLE 当前表名 ADD CONSTRAINT FOREIGN KEY(当前表的主键) REFERENCES 被关联表名(其他表主键);

方式1:通过修改表结构添加外键
-- 用户和资料表
-- 用户表
CREATE TABLE customer (
id INT PRIMARY KEY AUTO_INCREMENT,
user_name VARCHAR(50)
);
-- 资料表
CREATE TABLE extension(
id INT PRIMARY KEY AUTO_INCREMENT,
info VARCHAR(200)
);
-- 外键(主键)关联主键
ALTER TABLE extension
ADD CONSTRAINT FOREIGN KEY(id) REFERENCES customer(id);
方式2: 在创建表时候,直接建立外键
-- 用户表同上
-- 资料表
--创建字段关联id
CREATE TABLE extension2(
id INT PRIMARY KEY AUTO_INCREMENT,
info VARCHAR(200),
cid INT UNIQUE,
foreign key(cid) REFERENCES customer(id)
);
注意:物理外键(主)和逻辑外键方式2:通过建表时,添加外键约束
-- 测试数据
insert into customer values(1,'张三'),(2,"李四");
insert into extension values(1,'开发工程师');
insert into extension values(2,'测试工程师'); -- 报错,资料表时依赖于用户表
insert into customer values(1,'李四');
insert into extension values(2,'测试工程师'); -- 成功
insert into extension2 values(1,'开发工程师',100); -- customer中没有id=100

方式2:通过建表时,添加外键约束

创建表时候增加字段,用于外键约束:
创建新字段 INT UNIQUE
foreign key(当前表字段名) REFERENCES 被关联表(id)

-- 用户表
CREATE TABLE cus (
id INT PRIMARY KEY AUTO_INCREMENT,
user_name VARCHAR(50)
);
-- 资料表
--创建字段关联id
CREATE TABLE ex2(
id INT PRIMARY KEY AUTO_INCREMENT,
info VARCHAR(200),
cid INT UNIQUE,
foreign key(cid) REFERENCES cus(id)
);
注意:物理外键(主)和逻辑外键
-- 测试数据
insert into cus values(1,'张三');
insert into ex2 values(1,'开发工程师',1);
insert into ex2 values(2,'测试工程师',2); -- 报错,资料表时依赖于用户表
insert into cus values(1,'李四');
insert into ex2 values(2,'测试工程师'); -- 成功
insert into ex2 values(1,'开发工程师',100); -- customer中没有id=100  

注意:auto_increment:如果没有指定编号,那么根据当前表中最大编号按照递增顺序编号,即使数据
被删除,该编号也不会被再次利用

2 一对多关系

在多的表中创建外键与一的主键关联(常用)或是建立第三张表用于保存表id
商店和商品
班级与学生
方式1:在多的一方表中增加字段,去关联少的一方的主键

-- 商店表
CREATE TABLE shop(
id INT PRIMARY KEY,
sname VARCHAR(100)
);
-- 商品表
CREATE TABLE goods(
id INT PRIMARY KEY auto_increment,
gname VARCHAR(100),
price DOUBLE,
sid INT,
foreign key(sid) REFERENCES shop(id)
);
-- 在商店表中插入具体数据
insert into shop values(1,"华联"),(2,"沃尔玛");
-- 向商品表中增加数据
insert into goods values(1,'沙发',3999.9,1),(0,"电视",4888.8,1); --成功
insert into goods values(0,'笔记本',3999.9,3); -- 失败,shop不存在该编号  

方式2:新建一个关系表,用于关联之前两个表的各自主键。

-- 商店表
CREATE TABLE shop2(
	id INT PRIMARY KEY,
	sname VARCHAR(100)
);
-- 商品表
CREATE TABLE goods2(
	id INT PRIMARY KEY auto_increment,
	gname VARCHAR(100),
	price DOUBLE
);
-- 新建关系表
create table shop_goods(
	id int primary key,
	shop_id int,
	goods_id int unique,
	foreign key(shop_id) references shop2(id),
	foreign key(goods_id) references goods2(id)
);
-- 向goods2表中插入数据
insert into goods2 values (1,'沙发',999.9),(2,"电视",1999),(3,'笔记本',8999);
-- 向关系表中增加数据
insert into shop_goods values(1,2,3); --成功
insert into shop_goods values(2,2,3); -- 失败,同一个商品是能由一家卖
-- 向shop添加数据
insert into shop values (3,"家乐福");  
insert into shop_goods values(2,3,2); -- 成功
insert into shop_goods values(3,300,1); -- 失败,没有编号为300的店
3 多对多

创建第三方表用于记录各自主键
学生和学科
商品类型和商品

-- 创建学生表
create table students(
id int primary key auto_increment not null,
s_name varchar(10)
);
-- 创建学科表
create table courses(
id int primary key auto_increment not null,
c_name varchar(10)
);
--第三张表
create table stu_cos(
id int primary key auto_increment not null,
s_id int,
c_id int,
foreign key(s_id) REFERENCES students(id),
foreign key(c_id) references courses(id)
);
-- 向学生表和课程表中插入数据
insert into students values(1,'张三'),(2,"李四"),(3,"王五"),(4,"马六");
insert into courses values(1,"python"),(2,'java'),(3,"c++"),(4,'web');
-- 向关系表中插入数据
insert into stu_cou values
(1,1,1),(2,3,3),
(3,2,1),(4,1,2),
(5,2,2),(6,4,4),
(7,4,3),(8,3,1);  

( 二 ) 关联查询

1 外键关联查询

利用两张表之间的公共字段(外键)进行连接。

insert into shop_goods values(2,3,2); -- 成功
insert into shop_goods values(3,300,1); -- 失败,没有编号为300的店

SELECT * FROM employee as e, department as d
WHERE e.deptno = d.deptno
and d.deptname="近卫";
-- 查询部分字段
SELECT e.empname,e.salary,d.deptname FROM employee as e, department as d
WHERE e.deptno = d.deptno
and d.deptname="近卫";
-- 查询后勤部 部门的人数
SELECT count(*) FROM employee as e, department as d
WHERE e.deptno = d.deptno AND d.deptname="后勤部";
--需求:查询所有近卫部门员工的姓名和员工的部门
SELECT e.empname,d.deptname FROM employee as e, department as d
WHERE e.deptno = d.deptno AND d.deptname="近卫";
-- 查询员工工资超过20000的人员姓名,工资及部门
SELECT e.empname,d.deptname,e.salary FROM employee as e, department as d
WHERE e.deptno = d.deptno AND e.salary>20000;  
2 连接查询

当查询结果的列来源于多张表时,需要将多张表连接成一个大的数据集,再选择合适的列返回

(1) 内连接查询(inner join)

查询的结果为两个表都匹配的数据,相当于交集

在这里插入图片描述

select * from 第一张表名 inner join 第二张表名 on 两个表的共同字段;
-- 查询每个部门下都有哪些员工:部门和员工都要匹配即交集
SELECT * FROM employee
INNER JOIN department
ON employee.deptno = department.deptno;  
(2) 外连接查询(outer join)

左连接(left join):查询的结果为两个表匹配到的数据和左表特有的数据,对于右表中不存在的数
据使用null填充

在这里插入图片描述

-- 查询每个部门下的所有员工,没有部门的员工也要查询
SELECT * FROM department
LEFT JOIN employee
ON department.deptno = employee.deptno;  

右连接(right join):查询的结果为两个表匹配到的数据和右表特有的数据,对于左表中不存在的数
据使用null填充 在这里插入图片描述

-- 查询所有员工,没有员工的部门也查询
SELECT * FROM department
RIGHT JOIN employee
ON employee.deptno = department.deptno;  
3 子查询

在一个 select 语句中,嵌入了另外一个 select 语句, 那么被嵌入的 select 语句称之为子查询语句

(1) 单行子查询:返回一个数据
需求:查询杨志属于哪个部门
分析:杨志属于员工信息,但是查询部门需要在部门表中查询具体信息
案例操作:
select d.deptname from employee as e inner join department as d on
e.deptno=d.deptno where e.empname="杨志";
-- 子查询
SELECT * FROM department
WHERE deptno = (SELECT deptno FROM employee WHERE empname = "杨志");
-- 多表查询
select * from department, employee
where employee.deptno = department.deptno and employee.empname='杨志';
-- 连接查询
select * from department inner join employee
on employee.deptno = department.deptno where employee.empname='杨志';
(2)多行子查询:返回多个数据
需求:查询军委1部、军委2部、军委3部所有职员信息
分析:查询部门信息,得到部门编号,才能查询这些部门下所有的职员信息
案例操作:
-- 查询军委1部~3部所有职员信息
SELECT * FROM employee
WHERE deptno IN (SELECT deptno FROM department
WHERE deptname IN ("军委1部","军委2部","军委3部"));
-- 多表查询
select * from department, employee
where employee.deptno = department.deptno and deptname IN ("军委1部","军委2部","军
委3部");
-- 连接查询
select * from department inner join employee
on employee.deptno = department.deptno where deptname IN ("军委1部","军委2部","军委
3部");
4 扩展:自关联

设计省信息的表结构province
id
ptitle
设计市信息的表结构city
id
ctitle
pid
city表的pid表示城市所属的省,对应着province表的id值
问题:能不能将两个表合成一张表呢?
存储的都是地区信息,而且每种信息的数据量有限,没必要增加一个新表,或者将来还要存储区、乡镇信息,都增加新表的开销太大
答案:定义表areas,结构如下
id
title
pid
创建areas表的语句如下:

create table areas(
aid int primary key,
atitle varchar(20),
pid int
);

从sql文件中导入数据

source areas.sql;

查询一共有多少个省

select count(*) from areas where pid is null;

例1:查询省的名称为“河南省”的所有城市

select city.* from areas as city
inner join areas as province on city.pid=province.aid
where province.atitle='河南省';

例2:查询市的名称为“广州市”的所有区县

select dis.* from areas as dis
inner join areas as city on city.aid=dis.pid
where city.atitle='广州市';

二 事务

(一)数据库引擎

数据库存储引擎,是数据库底层构建的核心,负责底层数据持久化和软件交互的序列化操作、校验过程以及交互过程,通过数据库存储引擎完成创建、查询、更新和删除数据。不同的存储引擎提供不同的存储机制、索引技巧、锁定水平等功能,使用不同的存储引擎,还可以 获得特定的功能。
show engines; 查看数据库引擎
show variables like ‘%storage_engine%’; 查看默认引擎
1 InnoDB则是一种支持事务的引擎。支持行锁定和外键,InnoDB 是默认的 MySQL 引擎
2 MyISAM 基于 ISAM 存储引擎,并对其进行扩展。它是在 Web、数据仓储和其他应用环境下最常使用的存储引擎之一。MyISAM 拥有较高的插入、查询速度,但不支持事物。

(二)事务概述

一般是指要做的或所做的事情。在计算机术语中是指访问并可能更新数据库中各种数据项的一个程序执行单元(unit)。
将一组有序的增删改操作看一个基本执行单元,所有的操作都成功的条件下,事务才成有功,只要有一个操作失败,事 务要回滚。比如:银行转账,商品秒杀

(三)事务特性

事务在操作过程中,为了保障批量数据在批量操作过程中的数据安全性,制定了一些事务本身必须具备的特性,通过对这些特性约束的具体实现,保障事务执行的安全性和可靠性;这些特性被统称为ACID特性,分别为

原子性(atomicity)

事务包含的所有操作要么全部成功,要么全部失败回滚,因此事务的操作如果成功就必须要完全应用到数据库,如果操作失败则不能对数据库有任何影响。如A给B转帐,不会出现A的钱少了,B的钱却没有增加的情况

一致性(consistency)

事务开始前和结束后,数据库的完整性约束没有被破坏 。如转账业务完成后A减少100,B一定增加100

隔离性(isolation)

同一时间,只允许一个事务请求同一数据,不同的事务之间彼此没有任何干扰。即要达到这么一种效果:对于任意两个并发的事务T1和T2,在事务T1看来,T2要么在T1开始之前就已经结束,要么在T1结束之后才开始,这样每个事务都感觉不到有其他事务在并发地执行。

持久性(durability)

持久性是指一个事务一旦被提交了,那么对数据库中的数据的改变就是永久性的,即便是在数据库系统遇到故障的情况下也不会丢失提交事务的操作。

(四)事务隔离级别

根据处理数据的不同需求,MySQL内部定义了4种隔离级别,严格程度逐步加深

1 Read Uncommitted(读未提交)

在该级别,数据库遵循一级封锁协议。一个事务不能修改其他事务正在修改的数据,但是可以读取到其他事务修改但是尚未提交的数据,如果这些数据未被提交,被称为脏数据。出现这样的问题称为脏读

2 Read Committed(读已提交)

在 Read committed 策略下,数据库遵循二级封锁协议,只允许读取已经被提交的数据,即如果一个事务修改了某行数据但尚未提交,而第二个事务要读取这行数据的话,那么是看不到第一个事务修改的数据的。这种方式称为MVCC(多版本并发控制),通过此种方式就可以避免脏读的发生。但是,允许一个事务中多次相同查询得到不同的结果,就是所谓的不可重复读问题。

3 Repeatable Read(可重复读)

Repeat Read又比Read Committed更加严格一点,但仍然是在二级封锁协议的范畴,只是读取过程受到更多MVCC的影响。在Read Committed下,可能会出现不可重复读问题,但是这在一些应用中是允许的,比如oracle、SQL server上默认这一隔离级别。而MySQL则是Repeatable Read级别。在这一级别下,有赖于MVCC,同一个事务中的查询只能查到版本号不高于当前事务版本的数据,即事务只能看到该事务开始前或者被该事物影响的数据。也就是说,这一级别下,不允许事务读取在该事务开始后新提交的数据。即防止了不可重复读的发生。

依靠上面的机制,已经做到了在事务内数据内容的不变,但是不能保证多次查询得到的数据数量一致。因为在一个事务执行的过程中别的事务完全可以执行数据插入,当插入了刚好符合查询条件的数据时,就会引发数据查询结果集增加,引发幻读。还有一种情况就是,如果一个事务想插入一条数据,而另一个事务已经插入了含有相同主键的数据,那么当前事务也会被阻塞,并最终执行失败,虽然当前事务根本无法查询到这一条数据,这也是一种幻读。

4 Serializable(可串行化)

最强事务隔离机制 Serializable,它遵循三级封锁协议,使得所有的事务必须串行化执行,只要有事务
在对表进行查询,那么在此事务提交前,任何其他事务的修改都会被阻塞。这解决了一切并发问题,但
会造成大量的等待、阻塞甚至死锁,使系统性能降低,一般采用 Repeat Read 和数据库锁相结合方式
来替代它。

(五)事务并发问题

根据不同事物不同的隔离级别,可能会出现不同的问题。
脏读(dirty read):A事务读取B事务尚未提交的更改数据,并在这个数据基础上操作。如果B事务回
滚,那么A事务读到的数据根本不是合法的,称为脏读。
不可重复读(unrepeatable read):A事务读取了B事务已经提交的更改(或删除)数据。比如A事务
第一次读取数据,然后B事务更改该数据并提交,A事务再次读取数据,两次读取的数据不一样。
幻读(phantom read):A事务读取了或意识到了B事务已经提交的新增数据。对于不可重复读,只
需要采取行级锁防止该记录数据被更改或删除,然而对于幻读必须加表级锁,防止在这个表中新增一条
数据。

(六)事务操作

--查看事务的隔离级别:
select @@transaction_isolation;1 读未提交和脏读
-- 设置事务隔离级别
set session transaction isolation level 隔离级别;
-- 开启一个事务
start transaction;
或 begin;
-- 提交一个事务
commit;
-- 回滚一个事务
rollback;
1 读未提交和脏读
--创建数据库
create database trans charset=utf8mb4;
--改变数据库
use trans;
--准备数据表
create table students(
id int unsigned primary key auto_increment not null,
name varchar(20) default '',
age tinyint unsigned default 0
);
--添加数据
insert into students
values(0,'张三',20),(0,'李四',25);
--开启两个mysql终端,两个终端进行如下操作:
--1查看隔离级别和修改隔离级别
select @@transaction_isolation;
--2修改隔离级别
set session transaction isolation level Read Uncommitted;
-- 均开启事务
begin;
-- 其中一个终端1增加数据,不提交
insert into students values(0,'王五',30);
--另外一个终端2查看
select * from students;
-- 此时终端1回滚操作
rollback;  

在这里插入图片描述
在这里插入图片描述

2 读已提交和不可重复读
-- 修改事务隔离级别
set session transaction isolation level Read Committed;
-- 分别开启事务
start transaction;
-- 终端1查看数据
select * fron students;
--- 验证脏读问题
-- 其中一个终端2增加数据,不提交
insert into students values(0,'王五',30);
-- 终端1查看数据:数据未变,说明解决了脏读问题。
select * fron students;
-- 终端2修改数据,并提交数据
update students set age=22 where id=1;
--终端2提交数据
commit;
-- 终端1再次查看数据,出现与去之前结果不同,即不可重复读问题
select * fron students;

在这里插入图片描述

不可重复读

在这里插入图片描述

3 可重复读
-- 修改终端1、2事务隔离级别
set session transaction isolation level repeatable read;
-- 开启事务
begin;
-- 终端1查看数据
select * from students;
--终端2修改数据并提交
update students set age=20 where id=1;
commit;
-- 终端1再次查看数据,实现可重复读,数据仍没变
select * from students;

update 引起的幻读

--终端1查看数据
select * from students;
-- 终端2 修改年龄并提交
update students set age=20 where id=1;
commit;
--终端1也修改年龄,注意修改年龄时使用当前的年龄操作
update students set age=age+1;
--终端1再次查看数据,发现张三年龄并不是在之前10基础上增加1,而是在20基础上增加,那个20就是事务
2操作对事务1造成的影响---幻读
select * from students;

insert操作引起的幻读

delete引起的幻读

在这里插入图片描述

4 串行化
-- 修改终端1、2事务隔离级别
set session transaction isolation level serializable;
-- 开启事务
start transaction;
-- 任意一个终端进行增删改操作,发现会阻塞
insert into students values(0,'王五',22);

(七)总结

隔离级别脏读不可重复读幻读
读未提交可能可能可能
读已提交不可能可能可能
可重复读不可能不可能可能
可串行化不可能不可能不可能

事务更详细内容:https://juejin.im/post/5c9040e95188252d92095a9e
事务的隐式提交
使用 create 、 alter 、 delete 语句去修改数据库、表、视图、存储过程等数据库对象的时候,就会隐式提交当前事务。
使用 ALTER USER 、 CREATE USER 、 DROP USER 、 GRANT 、 RENAME USER 、 REVOKE 、 SETPASSWORD 等语句, 也会触发隐式提交。
还有很多操作多会造成隐式提交, 经常使用的则是对数据库表的增、删、改操作。

三 索引

(一)索引概述

一般的应用系统,读写比例在10:1左右,而且插入操作和一般的更新操作很少出现性能问题,遇到最多的,也是最容易出问题的,还是一些复杂的查询操作,所以查询语句的优化显然是重中之重。
在数据量和访问量不大的情况下,mysql访问是非常快的,是否加索引对访问影响不大。但是当数据量和访问量剧增的时候,就会发现mysql变慢,这就必须要考虑优化sql了,给数据库建立正确合理的索引,是mysql优化的一个重要手段。

(二) 索引种类

1 根据字段不同

UNIQUE(唯一索引):不允许其中任何两行具有相同索引值,可以有NULL值
INDEX(普通索引):允许出现相同的索引内容
PRIMARY KEY(主键索引):不允许出现相同的值,主键索引是唯一索引的特定类型。
fulltext index(全文索引):可以针对值中的某个单词,但效率不高,(FULLTEXT索引仅可用于MyISAM 表)
组合索引:实质上是将多个字段建到一个索引里,列值的组合必须唯一

2 根据索引和实际表顺序(了解)

聚集索引:索引中键值的逻辑顺序决定了表中相应行的物理顺序。
一个表只能包含一个聚集索引
类似知道读音,通过字母顺序直接查字典
非聚集索引:索引中索引的逻辑顺序与磁盘上行的物理存储顺序不同
一个表可以包含多个非聚集索引
类似于查字典,但是不清楚字的读音,通过偏旁部首查字

(三)索引优缺点

索引的目的在于提高查询效率,可以类比字典,如果要查“mysql”这个单词,我们肯定需要定位到m字母,然后从下往下找到y字母,再找到剩下的sql。如果没有索引,那么你可能需要把所有单词看一遍才能找到你想要的。除了词典,生活中随处可见索引的例子,如火车站的车次表、图书的目录等。它们的原理都是一样的,通过不断的缩小想要获得数据的范围来筛选出最终想要的结果,同时把随机的事件变成顺序的事件,也就是我们总是通过同一种查找方式来锁定数据。

在创建索引时,需要考虑哪些列会用于 SQL 查询,然后为这些列创建一个或多个索引。事实上,索引也是一种表,保存着主键或索引字段,以及一个能将每个记录指向实际表的指针。数据库用户是看不到索引的,它们只是用来加速查询的,数据库搜索引擎使用索引来快速定位记录。

INSERT 与 UPDATE 语句在拥有索引的表中执行会花费更多的时间,而SELECT 语句却会执行得更快。这是因为,在进行插入或更新时,数据库也需要插入或更新索引值。

1 优点
  • 通过创建唯一性索引,可以保证数据库表中每一行数据的唯一性。
  • 可以大大加快数据的检索速度,这也是创建索引的最主要的原因。
  • 可以加速表和表之间的连接。
  • 在使用分组和排序子句进行数据检索时,同样可以显著减少查询中分组和排序的时间。
2 缺点
  • 创建索引和维护索引要耗费时间,这种时间随着数据量的增加而增加。
  • 索引需要占物理空间,除了数据表占数据空间之外,每一个索引还要占一定的物理空间。
  • 当对表中的数据进行增加、删除和修改的时候,索引也要动态的维护,这样就降低了数据的维护速
    度。

(四)索引原理

1 hash索引

基于哈希表实现,只有精确匹配索引所有列的查询才有效,对于每一行数据,存储引擎都会对所有的索引列计算一个哈希码(hash code),并且Hash索引将所有的哈希码存储在索引中,同时在索引表中保存指向每个数据行的指针。
Hash索引能最快速的进行数据的定位,对于固定数据的查询效率是最高的,但是如果是范围查询的情况,由于Hash索引的不连续性,查询性能会下降。

在这里插入图片描述

2 B-Tree(平衡多路查找树)

在这里插入图片描述

模拟查找关键字29的过程:

  1. 根据根节点找到磁盘块1,读入内存。【磁盘I/O操作第1次】
  2. 比较关键字29在区间(17,35),找到磁盘块1的指针P2。
  3. 根据P2指针找到磁盘块3,读入内存。【磁盘I/O操作第2次】
  4. 比较关键字29在区间(26,30),找到磁盘块3的指针P2。
  5. 根据P2指针找到磁盘块8,读入内存。【磁盘I/O操作第3次】
  6. 在磁盘块8中的关键字列表中找到关键字29。

从B-Tree结构图中可以看到每个节点中不仅包含数据的key值,还有data值。而每一个节点的存储空间是有限的,如果data数据较大时将会导致每个节点能存储的key的数量很小,当存储的数据量很大时同样会导致B-Tree的深度较大,增大查询时的磁盘I/O次数,进而影响查询效率。

3 B+Tree

B+Tree是在B-Tree基础上的一种优化,使其更适合实现外存储索引结构,InnoDB存储引擎就是用B+Tree实现其索引结构。
在B+Tree中,所有数据记录节点都是按照键值大小顺序存放在同一层的叶子节点上,而非叶子节点上只存储key值信息,这样可以大大加大每个节点存储的key值数量,降低B+Tree的高度。
B+Tree相对于B-Tree有几点不同:

  1. 非叶子节点只存储键值信息。
  2. 所有叶子节点之间都有一个链指针。
  3. 数据记录都存放在叶子节点中。
    在这里插入图片描述

(五)索引操作

1 创建索引
(1)使用ALTER TABLE语句创建索性

应用于表创建完毕之后再添加。 ALTER TABLE 表名 ADD 索引类型 (unique,primarykey,fulltext,index)[索引名](字段名)

-- 普通索引
alter table table_name add index index_name (column_list) ;
alter table students add index stu (name,age);
-- 唯一索引
alter table table_name add unique (column_list);
alter table students add unique stu (name,age);
-- 主键索引:由于本身主键就是一个主键索引,所以不能再创建
alter table table_name add primary key (column_list) ;
alter table students add primary key (id);

ALTER TABLE可用于创建普通索引、UNIQUE索引和PRIMARY KEY索引3种索引格式,table_name是要增加索引的表名,column_list指出对哪些列进行索引,多列时各列之间用逗号分隔。索引名index_name可选,缺省时,MySQL将根据第一个索引列赋一个名称。

(2) 使用CREATE INDEX语句对表增加索引

CREATE INDEX可用于对表增加普通索引或UNIQUE索引,可用于建表时创建索引。

-- create只能添加这两种索引;
CREATE INDEX index_name ON table_name (column_list)
CREATE UNIQUE INDEX index_name ON table_name (column_list)

注意:table_name、index_name和column_list具有与ALTER TABLE语句中相同的含义,索引名不可选。另外,不能用CREATE INDEX语句创建PRIMARY KEY索引

2 删除索引

删除索引可以使用ALTER TABLE或DROP INDEX语句来实现。DROP INDEX可以在ALTER TABLE内部作为一条语句处理,其格式如下:

drop index index_name on table_name ;
alter table table_name drop index index_name ;
alter table table_name drop primary key ;

其中,在前面的两条语句中,都删除了table_name中的索引index_name。而在最后一条语句中,只在删除PRIMARY KEY索引中使用,因为一个表只可能有一个PRIMARY KEY索引,因此不需要指定索引名。如果没有创建PRIMARY KEY索引,但表具有一个或多个UNIQUE索引,则MySQL将删除第一个UNIQUE索引。
如果从表中删除某列,则索引会受影响。对于多列组合的索引,如果删除其中的某列,则该列也会从索
引中删除。如果删除组成索引的所有列,则整个索引将被删除。

3 查看索引

SHOW INDEX FROM 表名;

4 示例

查看索引

在这里插入图片描述

添加索引

在这里插入图片描述

drop index 删除索引

在这里插入图片描述
在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值