Mysql从入门到入魔——9. 游标、高级SQL特性
- 1. 游标
- 1.1 使用游标
- 1.2 创建游标
- 1.3 使用游标数据
- 1.4 游标的优缺点
- 2. 约束
- 2.1 约束
- 2.2 主键
- 2.3 外键
- 2.4 唯一约束
- 2.5 检查约束
- 3. 索引
- 3.1 普通索引
- 3.2 唯一索引
- 3.3 全局索引
- 3.4 多列索引
本篇主要内容
游标的使用、常见的约束及创建方式、INNODB 中常见索引的介绍及用法。话不多说,进入正题!
 
 

 
1. 游标
SQL 检索操作返回结果集,简单地使用 SELECT 语句,没有办法得到第一行、下一行或前 10 行。有时,需要在检索出来的行中前进或后退一行或多行,这就是游标的用途所在。游标(cursor)是一个存储在 DBMS 服务器上的数据库查询, 它不是一条 SELECT 语句,而是被该语句检索出来的结果集。在存储了 游标之后,应用程序可以根据需要滚动或浏览其中的数据。
1.1 使用游标
游标使用的步骤:
- 在使用游标前,必须声明(定义)它。这个过程实际上没有检索数据, 它只是定义要使用的 SELECT语句和游标选项。
- 一旦声明,就必须打开游标以供使用。这个过程用前面定义的 SELECT语句把数据实际检索出来。
- 对于填有数据的游标,根据需要取出(检索)各行。
- 在结束游标使用时,必须关闭游标,可能的话,释放游标。
声明游标后,可以根据需要频繁地 打开或关闭 游标。在游标打开时,可根据需要频繁地执行 取 操作。
注意:不像多数DBMS,MySQL游标只能用于存储过程(和函数)。
 
1.2 创建游标
使用 DECLEAR 来创建游标,DECLARE 命名游标,并定义相应的 SELECT 语句,根据需要带 WHERE 和 其他子句。
下面的语句定义了名为 ordernumbers 的游标,使用了可以检索所有订单的 SELECT 语句。
Order表中的信息:
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DErmf7Xm-1624782633855)(C:\Users\pc\AppData\Roaming\Typora\typora-user-images\image-20210620133220056.png)] mysql游标使用变量作为表名_数据_02](https://s2.51cto.com/images/blog/202411/30151559_674abbaff1a6747864.png?x-oss-process=image/watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_30,g_se,x_10,y_10,shadow_20,type_ZmFuZ3poZW5naGVpdGk=/resize,m_fixed,w_1184)
DROP PROCEDURE IF EXISTS processorder;
CREATE PROCEDURE processorder()
BEGIN
	-- 定义游标
	DECLARE ordernumbers CURSOR
	FOR
	SELECT order_num FROM orders;
END;这个存储过程中,使用 DECLARE 语句用来定义和命名游标。存储过程处理完成后,游标就消失(因为它局限于存储过程)。
 
1.3 使用游标数据
使用 OPEN 语句来打开游标,CLOSE 语句关闭游标,在一个游标被打开后,可以使用 FETCH 语句分别访问它的每一行。FETCH 指定检索的数据(所需的列),数据存储的位置(定义的变量)。 它还向前移动游标中的内部行指针,使下一条 FETCH 语句检索下一行(不重复读取同一行)。
DROP PROCEDURE IF EXISTS processorder;
CREATE PROCEDURE processorder()
BEGIN
    -- 定义局部变量
    DECLARE num INT;
    -- 定义游标
    DECLARE ordernumbers CURSOR
    FOR
    SELECT order_num FROM orders;
    -- 打开游标
    OPEN ordernumbers;
    -- 获取第一行数据
    FETCH ordernumbers INTO num;
    -- 查询结果
    SELECT num;
    -- 关闭游标
    CLOSE ordernumbers;
END;
CALL processorder();![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fVY62sKB-1624782102620)(C:\Users\pc\AppData\Roaming\Typora\typora-user-images\image-20210620133320907.png)] mysql游标使用变量作为表名_mysql_03](https://s2.51cto.com/images/blog/202411/30151600_674abbb02599e1333.png?x-oss-process=image/watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_30,g_se,x_10,y_10,shadow_20,type_ZmFuZ3poZW5naGVpdGk=/resize,m_fixed,w_1184)
其中 FETCH 用来检索当前行的 order_num 列(将自动从第一行开始)到一个名为 num 的局部变量中,并将查询 num 的结果。由于只检索到第一行,所以 num 的值为 ‘20005’。
下面,循环检索数据,从第一行到最后一行。
DROP PROCEDURE IF EXISTS processorder;
CREATE PROCEDURE processorder()
BEGIN
	-- 定义局部变量
	DECLARE done BOOLEAN DEFAULT false;
	DECLARE num INT;
	-- 定义游标
	DECLARE ordernumbers CURSOR
	FOR
	SELECT order_num FROM orders;
	-- 定义CONTINUE HANDLER
	DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET done=true;
	-- 打开游标
	OPEN ordernumbers;
	-- 循环所有行
	REPEAT
		-- 获取第一行数据
		FETCH ordernumbers INTO num;
	-- 结束循环
	UNTIL done END REPEAT;
	-- 查询结果
	SELECT num;
	-- 关闭游标
	CLOSE ordernumbers;
END;
CALL processorder();![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UuxHnptl-1624782102623)(C:\Users\pc\AppData\Roaming\Typora\typora-user-images\image-20210620132917151.png)] mysql游标使用变量作为表名_mysql_04](https://s2.51cto.com/images/blog/202411/30151600_674abbb06869211775.png?x-oss-process=image/watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_30,g_se,x_10,y_10,shadow_20,type_ZmFuZ3poZW5naGVpdGk=/resize,m_fixed,w_1184)
循环了结果集的所有行,所以 num 的值是最后一行的数据。
与上一个例子不同之处是,这个例子的 FETCH 是在 REPEAT 内,因此它反复执行直到 done 为真。
DECLARE CONTINUE HANDLER FOR SQLSTATE ‘02000’ SET done=true;
这条语句定义了一个 CONTINUE HANDLER,它是在条件出现时被执行的代码。这里,它指出当 SQLSTATE '02000' 出现时,SET done=true。SQLSTATE '02000'是一个未找到条件,当 REPEAT 由于没有更多的行供循环而不能继续时,出现这个条件。
 
1.4 游标的优缺点
优点:游标是面向集合与面向行的设计思想之间的一种桥梁,因为游标是针对行操作的,所以对从数据库中 SELECT 查询得到的每一行可以进行分开的独立的相同或不同的操作,是一种分离的思想。可以满足对某个结果行进行特殊的操作。如基于游标位置的增删改查能力。
缺点:
- 速度较慢
- 会产生死锁现象
- 内存大
2. 约束
2.1 约束
DBMS 通过在数据库表上施加约束来实施引用完整性。大多数约束是在表定义中定义的,用 CREATE TABLE 或是 ALTER TABLE 语句。
 
2.2 主键
主键是一种特殊的约束,用来保证一列(或 一组列)中的值是唯一的,而且永不改动。没有主键,要安全地 UPDATE 或 DELETE 特定行而不影响其他行会 非常困难。
主键的条件:
- 任意两行的主键值都不相同。
- 每行都具有一个主键值(即列中不允许 NULL值)。
创建表时定义主键。
CREATE TABLE teacher
(
	id INT(11) PRIMARY KEY,
	teacher_name VARCHAR(10)
);使用 ALTER TABLE 添加主键。
ALTER TABLE teacher
ADD CONSTRAINT PRIMARY KEY(id);删除主键约束。
ALTER TABLE teacher DROP PRIMARY KEY; 
2.3 外键
外键是表中的一列,其值必须列在另一表的主键中。外键是保证引用完 整性的极其重要部分。
下面新建 student 表并添加外键 teacher_id 与 teacher 表中的主键 id 进行关联。
在创建表的时定义外键。
CREATE TABLE student
(
	stu_id INT(11) PRIMARY KEY,
	teacher_id INT(11) REFERENCES teacher(id),
	stu_name VARCHAR(10)
);使用 ALTER TABLE 添加外键。
ALTER TABLE student
ADD CONSTRAINT teacher_id_id
FOREIGN KEY (teacher_id) REFERENCES teacher(id);使用外键可以有效地防止意外删除,比如在上面两表中如果删除 teacher 表中的信息,如果该 id 在 student 表中也有出现,那么 Mysql 会防止删除操作。当然也可以启用级联删除的特性,那么在删除时就会删除所有相关信息。
删除外键。
ALTER TABLE student DROP FOREIGN KEY teacher_id_id; 
2.4 唯一约束
唯一约束用来保证一列(或一组列)中的数据是唯一的。它们类似于主 键,但存在以下重要区别。
- 表可包含多个唯一约束,但每个表只允许一个主键。
- 唯一约束列可包含 NULL值。
- 与主键不一样,唯一约束不能用来定义外键。
在创建表的时定义唯一约束。
CREATE TABLE student
(
	stu_id INT(11) PRIMARY KEY,
	teacher_id INT(11) REFERENCES teacher(id),
	stu_name VARCHAR(10)
);使用 ALTER TABLE 添加唯一约束。
ALTER TABLE student
ADD CONSTRAINT unique_id UNIQUE(stu_id);删除唯一性约束。
ALTER TABLE student DROP INDEX unique_id; 
2.5 检查约束
检查约束用来保证一列(或一组列)中的数据满足一组指定的条件。
常见用途:
- 检查最小或最大值。
- 指定范围。
- 只允许特定的值。
下面创建一个检查约束来限制性别列只能输入男、女。
在创建表的时定义检查约束。
CREATE TABLE student
(    
    stu_id INT(11) PRIMARY KEY,
	gender VARCHAR(1) CHECK(gender IN('男', '女'))
);使用 ALTER TABLE 添加检查约束。
ALTER TABLE student ADD CONSTRAINT check_gender CHECK(gender in ('男', '女'));删除检查约束。
ALTER TABLE student DROP CHECK check_gender;3. 索引
索引用来排序数据以加快搜索和排序操作的速度。主键数据总是排序的, 因此,按主键检索特定行总是一种快速有效的操作。但是,搜索其他列中的值通常效率不高。这时候我们可以使用索引,在一个或多个列上定义索引,使 DBMS保存其内容的一个排过序的列表。在定义了索引后,DBMS 以使用书的索引类似的方法使用它。DBMS 搜索排过序的索引,找出匹配的位置,然后检索这些行。
索引特点:
- 索引提高检索的性能,但降低了数据增删改的性能。 在执行这些操作时,DBMS必须动态地更新索引。
- 索引数据可能要占用大量的存储空间。
- 并非所有数据都适合做索引。取值不多的数据(如地区)不如具有更多可能值的数据(如姓名),能够更加体现索引的价值。
- 索引用于数据过滤和数据排序。如果你经常以某种特定的顺序排序数据,则该数据可能适合做索引。
- 可以在索引中定义多个列(例如,国家 + 城市)。
3.1 普通索引
在创建表的时创建普通索引。
DROP TABLE IF EXISTS student;
CREATE TABLE student
(    
  	id INT(11),
	stu_name VARCHAR(10)
)直接创建。
CREATE INDEX stu_id ON student(id);修改表时创建。
ALTER TABLE student ADD INDEX stu_id(id);删除索引。
DROP INDEX stu_id ON student; 
3.2 唯一索引
唯一索引列值必须唯一,但允许有空值(注意和主键不同)。如果是组合索引,则列值的组合必须唯一。事实上,在许多场合,创建唯一索引的目的往往不是提高访问速度,而是为了避免数据出现重复。
CREATE UNIQUE INDEX stu_id ON student(id); 
3.3 全局索引
全文索引只能作用在 CHAR、VARCHAR、TEXT、类型的字段上。创建全文索引需要使用 FULLTEXT 参数进行约束。
CREATE FULLTEXT INDEX s_name ON student(stu_name); 
3.4 多列索引
多列索引,即在数据表的多个字段上创建索引。
CREATE TABLE student
(    
  id INT(11),
	stu_name VARCHAR(10),
	email VARCHAR(20),
	INDEX info(stu_name, email)
);在多列索引中,只有查询条件中使用了这些字段中的第一个字段(即上面示例中的 stu_name 字段),索引才会被使用(最左前缀’原则)。如果没有用到第一字段,则索引不起任何作用。
-- 使用索引
SELECT * FROM student WHERE stu_name = '张三';
SELECT * FROM student WHERE stu_name = '李四' AND email = '11111@';
-- 未使用索引
SELECT * FROM student WHERE email = '11111@';参考链接:
【详细解析】MySQL索引详解( 索引概念、6大索引类型、key 和 index 的区别、其他索引方式)
这就是本文所有的内容了
后续会继续分享《Mysql从入门到入魔》系列文章
                
 
 
                    
 
            
        













 
                    

 
                 
                    