概述

描述事物的符号记录称为数据,其特点是数据与其语义是不可分的。

四个基本概念

数据库(Database,DB):长期储存在计算机内有组织可共享大量数据的集合。
数据库管理系统(Database ManagementSystem,DBMS):位于用户与操作系统之间的一层数据管理软件。它和操作系统一样是计算机的基础软件,也是一类大型复杂的软件系统。
数据库系统(DataBaseSystem,DBS):引入数据库后的计算机系统。一般是指由数据库、数据库管理系统(及其应用开发工具)、应用系统和数据库管理员组成的存储、管理、处理和维护数据的系统。

数据库系统架构图(图源:March)

 数据库的本质:它是由DBMS创建的逻辑数据集合,没有安装DBMS的话,电脑中不存在可被管理的数据库;只有通过安装的MySQL/Oracle这种软件,才能在电脑的存储介质(硬盘、内存)上创建、存储和维护数据库。
 一句话:先装MySQL(DBMS),再用它创建数据库,数据库是DBMS运行后产生的产物,而非电脑自带的内容。

数据管理技术

数据管理是指对数据进行分类、组织、编码、存储、检索和维护。

数据管理技术发展历程:人工管理阶段->文件系统管理阶段->数据库系统阶段

数据库系统的特点:
(1)数据结构化
(2)数据的共享性高,冗余度低且易扩充
(3)数据独立性高(当数据的物理存储、逻辑结构改变了,应用程序不用改变。)
(4)数据由数据库管理系统统一管理和控制(以保证数据的完整性和安全性,并在多用户同时使用数据库时进行并发控制,在发生故障后对数据库进行恢复。)

数据库出现后:
◆以加工数据的程序为中心->以共享数据库为中心;
◆以软件为中心->以数据为中心。

数据模型

按照数据建模的过程可以把模型划分为概念模型和数据模型。
概念模型按用户的观点来对数据建模。它用于信息世界的建模。
概念模型的一种表示方法:实体-联系模型(E-R模型)
两个实体型之间的三类联系:
①一对一联系(1∶1)
②一对多联系(1∶n)
③多对多联系(m∶n)

数据模型按计算机系统的观点对数据建模 ,用于DBMS实现。
数据模型三要素:数据结构、数据操纵、完整性约束
数据模型分为两类:逻辑模型物理模型

逻辑模型主要包括层次模型、网状模型、关系模型、面向对象数据模型、对象关系数据模型、半结构化的XML数据模型等。
物理模型是对数据最底层的抽象 ,描述数据在系统内部的表示方式和存取方法 ,在磁盘或磁带上的存储方式和存取方法。

层次模型:树的形式组织数据
网状模型:图的形式组织数据
关系模型:表的形式组织数据

关系模型的数据结构
(1)关系:一个关系对应通常说的一张二维表。
(2)元组:表中的一行即为一个元组。
(3)属性:表中的一列即为一个属性,给每一个属性起一个名称即属性名。
(4)主码:也称码键。表中的某个属性组,它可以唯一确定一个元组。
(5)域:一属性的取值范围。例如,性别的域是(男,女)。
(6)分量:元组中的一个属性值。
(7)关系模式:对关系的描述,一般表示为:关系名(属性1,属性2,…,属性n)。

数据库系统的三级模式结构

数据库系统的三级模式结构是指数据库系统是由外模式、模式和内模式三级构成。

数据库系统的三级模式是对数据的三个抽象级别,这三级模式之间还提供了两级映像,即外模式/模式映像、模式/内模式映像,保证了数据库系统中的数据能够具有较强的逻辑独立性和物理独立性。

各人员的数据视图:

关系数据库

是一组具有相同数据类型的值的集合。
笛卡尔积是域上的一种集合运算。
是一个属性或多个属性,有特殊的性质。

(1)若关系模式中的某一个属性或一组属性的值能唯一地标识一个元组,而它的真子集不能唯一地标识一个元组,则称该属性或属性组为候选码(candidate key)。
(2)若一个关系有多个候选码,则选定其中一个为主码(primary key),或称主键
(3)候选码的诸属性称为主属性。不包含在任何候选码中的属性称为非主属性非码属性
(4)所有字段加起来才是唯一标识的叫做全码

关系操作包括查询和更新操作。
◆查询操作:选择、投影、连接、除、并、差、交、笛卡尔积。
◆数据更新:插入、删除、修改。

选择、投影(选出需要的列)、并、差、笛卡尔基是5种基本操作。

关系模型中的三类完整性约束:实体完整性、参照完整性、用户定义的完整性
◆实体完整性约束的是表的主键,主键字段不能重复、不能为 NULL。
◆参照完整性约束的是外键,保证 “子表的外键值必须是父表主键已存在的值,或为 NULL”。
◆用户定义的完整性是根据具体业务需求自定义的约束,既不是主键也不是外键,而是针对字段的“业务规则”。

关系代数

关系代数是一种抽象的查询语言,它用对关系的运算来表达查询。

R×S 笛卡尔积
列:(n+m) 列元组的集合
行:k1×k2个元组
选择
例1:请写出对应的关系代数,查询信息系(IS系)全体学生。σSdept = ‘IS’ (Student)
例2:请写出对应的关系代数:查询年龄小于20岁的学生。σSage < 20 (Student)
投影是从列的角度进行的运算,即从垂直方向进行抽取。
例:查询学生的姓名和所在系,请写出对应关系代数。πSname,Sdep (Student)
连接也称为 θ 连接,接是将关系R和关系S按相应属性值的比较条件连接成一个新的关系,它是R与S的笛卡尔积的一个子集。
等值连接、自然连接、外连接(外连接、左外连接、右外连接)。

除操作是同时从行和列角度进行运算。(涉及象集)

关系数据库标准语言SQL

SQL功能 动词
数据定义 create、drop、alter
数据查询 select
数据操纵 insert、update、delete
数据控制 grant、revoke

创建表

1
2
3
4
5
6
7
8
9
10
11
12
13
show databases;
create database studb;
use studb;

-- 学生表(Student):主键Sno唯一标识学生
CREATE TABLE Student (
Sno CHAR(10) PRIMARY KEY, -- 学号(如2023001001)
Sname VARCHAR(20) NOT NULL, -- 姓名(非空)
Ssex CHAR(2) CHECK (Ssex IN ('男', '女')), -- 性别(限制为男/女)
-- Ssex ENUM('男', '女') DEFAULT '男',
Sage INT CHECK (Sage > 0), -- 年龄(正数)
Sdept VARCHAR(30) -- 所在院系(如计算机学院)
);

Char(n):定长存储,n<255。
Varchar(n):不定长存储(按实际长度存储),长度最大不超过n 。

约束
主键约束 、非空约束、唯一性约束、检查约束、默认约束。

1
2
3
4
5
6
7
8
9
10
create table Student
(
Sno char(9) primary key,
Sname char(20) not null unique,
Ssex char(3) check(Ssex= ‘男’ or Ssex= ‘女’ ),
Sage smallint
constraint c1 check (Sage >15 or Sage<50),
Sdept char(20) default ‘CS’
);
drop constraint c1;

一个表只能有一个字段使用auto_increment约束,且该字段必须设置为主键。

为已有的表添加外键约束 foreign key:
alter table 从表名 add constraint 外键名 foreign key(从表的外键字段名) references 主表名 (主表的主键字段名)
删除外键约束 foreign key:
alter table 从表名 drop foreign key 外键名

修改基本表

1
2
3
4
alter table<表名>
[ ADD <新列名> <数据类型> [ 完整性约束 ] ]
[ DROP <完整性约束名> ]
[ ALTER COLUMN<列名> <数据类型> ];

◆修改表名:alter table stu1 rename (to) stu2;
◆修改字段名和数据类型:ALTER TABLE 表名 change 旧字段名 新字段名 新数据类型;

◆修改字段名:alter table 表名 modify 字段名 新数据类型;
◆修改字段的排列位置:alter table 表名 modify 字段名1 新数据类型 first|after 字段名2;

◆添加字段:alter table 表名 add 新字段名 数据类型 [约束条件][FIRST|AFTER已经存在的字段名];
◆删除字段:alter table 表名 drop 字段名;

查询

基础查询→条件查询→多表关联→进阶查询

1
2
3
4
5
6
7
8
9
select 要查询的字段/表达式
from 数据来源表
[where 行筛选条件] -- 可选:只查符合条件的行
[group by 分组字段] -- 可选:按字段分组统计
[having 分组筛选条件] -- 可选:筛选分组后的结果
[order by 排序字段 [ASC/DESC]] -- 可选:按字段排序(ASC升序,DESC降序)
[limit 限制返回条数] -- 可选:只返回前N条数据
[limit 1 offset 2] -- offset表示跳过前两行
[limit m,n] -- 跳过前m条记录,获取n条记录

基础查询

◆用*代表“所有字段”,适合快速预览表数据,但生产环境尽量不用(性能差)。
◆用 AS 给字段 / 表名起别名。
◆用 distinct 去除查询结果中的重复行。

1
2
3
4
5
6
7
8
-- 查询Student表中所有学生的所有信息
select * from student;

-- 查询所有学生的学号、姓名、所在系
SELECT Sno, Sname, Sdept FROM Student;

-- 查询学生的所有院系(不重复)
SELECT DISTINCT Sdept FROM Student;

条件查询

用 WHERE 筛选符合条件的行,是查询的核心技巧,常用条件运算符如下:

运算符 作用 示例
= 等于 Ssex = '男'
!=/<> 不等于 Sdept <> '计算机系'
>/< 大于 / 小于 Sage > 20
>=/<= 大于等于 / 小于等于 Sage <= 22
BETWEEN...AND... 区间(闭区间) Sage BETWEEN 18 AND 22
IN(值1,值2) 匹配多个值 Sdept IN ('计算机系','数学系')
LIKE 模糊匹配 Sname LIKE '张%'
IS NULL 为空 Cpno IS NULL
IS NOT NULL 不为空 Grade IS NOT NULL
AND/OR 多条件(且 / 或) Ssex='女' AND Sage>20

例: 查询订单中支付手段为“微信、支付宝、网银“的订单信息。

1
2
3
4
5
6
SELECT
    *
FROM
    orders
WHERE
    vPayType IN ('微信', '支付宝', '网银');

排序查询

用 ORDER BY 对查询结果排序,默认升序(ASC),降序用 DESC

1
2
3
4
5
6
7
8
-- 1. 按学生年龄升序排列(从小到大)
SELECT Sname, Sage FROM Student ORDER BY Sage;

-- 2. 按成绩降序排列(从高到低),成绩相同按学号升序
SELECT Sno, Cno, Grade FROM SC ORDER BY Grade DESC, Sno ASC;

-- 3. 查询计算机系学生,按年龄降序
SELECT Sname, Sage FROM Student WHERE Sdept='计算机系' ORDER BY Sage DESC;

例: 查询每种支付手段的订单的最高订单金额、最低订单金额和平均订单金额。

1
SELECT vPayType, MAX(mTotalCost) AS '最高订单金额', MIN(mTotalCost) AS '最低订单金额', AVG(mTotalCost) AS '平均订单金额' FROM orders GROUP BY vPayType;

这里要注意还要查询vPayType,否则不会显示是哪一种支付手段。

聚合查询

用聚合函数对数据做统计,常用聚合函数。

函数 作用 示例
COUNT(*) 统计行数 COUNT(*)(所有行)
COUNT(字段) 统计非空行数 COUNT(Grade)(成绩非空的行数)
SUM(字段) 求和 SUM(Ccredit)(总学分)
AVG(字段) 平均值 AVG(Grade)(平均成绩)
MAX(字段) 最大值 MAX(Grade)(最高成绩)
MIN(字段) 最小值 MIN(Grade)(最低成绩)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
-- 1. 统计学生总数
SELECT COUNT(*) AS 学生总数 FROM Student;

-- 2. 统计001号课程的平均成绩(排除成绩为空的)
SELECT AVG(Grade) AS 平均成绩 FROM SC WHERE Cno = '001';

-- 3. 统计每个学生的修课门数(按学号分组)
SELECT Sno, COUNT(Cno) AS 修课门数 FROM SC GROUP BY Sno;

-- 4. 统计每个课程的最高成绩、最低成绩
SELECT Cno, MAX(Grade) AS 最高分, MIN(Grade) AS 最低分 FROM SC GROUP BY Cno;

-- 5. 筛选修课门数≥3的学生(HAVING筛选分组结果,WHERE筛选行)
SELECT Sno, COUNT(Cno) AS 修课门数
FROM SC
GROUP BY Sno
HAVING COUNT(Cno) >= 3;

◆where与having的区别:

对比维度 WHERE HAVING
筛选时机 分组(GROUP BY)之前 分组(GROUP BY)之后
筛选对象 原始行数据(单条记录) 分组后的聚合结果(统计值)
能否用聚合函数 ❌ 不能(比如不能写 WHERE AVG(Grade)>60 ✅ 能(比如 HAVING AVG(Grade)>60
适用场景 筛选单条记录的条件(比如 “学号 = 001”“金额 > 0”) 筛选分组统计的条件(比如 “平均成绩> 60”“订单数≥5”)
语法位置 必须在 FROM 之后、GROUP BY 之前 必须在 GROUP BY 之后

连接查询

实际开发中,数据分散在多张表,需要通过关联字段(外键) 拼接查询,核心是 JOIN

关联类型 作用 语法
内连接(INNER JOIN) 只查两表匹配的数据 A JOIN B ON A.字段=B.字段
左连接(LEFT JOIN) 查左表所有数据,右表匹配不到则为 NULL A LEFT JOIN B ON A.字段=B.字段
右连接(RIGHT JOIN) 查右表所有数据,左表匹配不到则为 NULL A RIGHT JOIN B ON A.字段=B.字段
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
-- 1. 内连接:查询学生的姓名、修课的课程名、成绩(只查有成绩的)
SELECT s.Sname, c.Cname, sc.Grade
FROM Student s
JOIN SC sc ON s.Sno = sc.Sno -- 学生表和修课表通过学号关联
JOIN Course c ON sc.Cno = c.Cno; -- 修课表和课程表通过课程号关联

-- 2. 左连接:查询所有学生的姓名及修课成绩(没修课的学生成绩为NULL)
SELECT s.Sname, sc.Grade
FROM Student s
LEFT JOIN SC sc ON s.Sno = sc.Sno;

-- 3. 查询“计算机系”学生的修课情况(姓名、课程名、成绩)
SELECT s.Sname, c.Cname, sc.Grade
FROM Student s
JOIN SC sc ON s.Sno = sc.Sno
JOIN Course c ON sc.Cno = c.Cno
WHERE s.Sdept = '计算机系';

嵌套查询

1
2
3
SELECT Sno
FROM SC
WHERE Cno=1 AND Sno IN (SELECT Sno FROM SC WHERE Cno=2);

可以用 = 代替IN

1
2
3
SELECT Sno, Cno
FROM SC x
WHERE Grade >= ( SELECT AVG(Grade) FROM SC y WHERE y.Sno=x.Sno );

◆ANY
①使用关键字ANY时,只要满足内层查询语句返回的结果中的任何一个,就可以通过该条件来执行外层查询语句;
② 关键字ALL刚好相反,只有满足内层查询语句的所有结果,才可以执行外层查询语句。

例:查询其他系中比计算机科学某一学生年龄小的学生姓名和年龄。

1
2
3
SELECT Sname, Sage
FROM Student
WHERE Sage < ANY (SELECT Sage FROM Student WHERE Sdept='CS') AND Sdept <>'CS';

!=(或<>)ANY 不等于子查询结果中的某个值

◆EXISTS
带有EXISTS谓词的子查询不返回任何数据,只产生逻辑真值“true”或逻辑假值“false” 。

例:查询所有选修了1号课程的学生姓名。(用嵌套查询)

1
2
3
SELECT Sname
FROM Student
WHERE EXISTS ( SELECT * FROM SC WHERE Sno=Student.Sno AND Cno= '1');

理解:如果子查询能查到至少 1 条记录,等到遍历完所有学生,最终主查询返回所有 “验证为真” 的学生姓名。

数据更新

插入数据

插入元组
例:将一个新学生元组(学号:200215128;姓名:陈冬;性别:男;所在系:IS;年龄:18岁)插入到Student表中。

1
2
INSERT INTO Student (Sno, Sname, Ssex, Sdept, Sage)
VALUES ('200215128' , '陈冬', '男' , 'IS', 18);

插入子查询结果(可以一次插入多个元组)
例:对每一个系,求学生的平均年龄,并把结果存入数据库。

1
2
3
4
5
6
7
8
第一步:建表
create table dept_age(
sdept char(15), /* 系名*/
avg_age smallint /*学生平均年龄*/
);

第二步:插入数据
insert into Dept_age (Sdept,Avg_age) SELECT Sdept,AVG(Sage) FROM Student GROUP BY Sdept;

修改数据

UPDATE <表名> SET <列名>=<表达式>[WHERE <条件>];

删除数据

DELETE FROM <表名> [WHERE <条件>];

索引

根据索引的类型普通索引、唯一索引(允许字段为NULL)、复合索引、主键索引、全文索引等。

◆建立索引:create unique index idx_student_sno on Student(Sno);
主键字段会自动生成主键索引,若创建表时未指定主键,也可通过以下方式添加(本质是给主键加索引):

1
2
3
4
5
6
7
8
-- 方式1:创建表时指定主键(自动生成主键索引)
CREATE TABLE student (
id INT PRIMARY KEY,
name VARCHAR(20)
);

-- 方式2:给已有表添加主键(自动生成主键索引)
ALTER TABLE student ADD PRIMARY KEY (id);

◆删除索引:drop index <索引名>

什么情况下,我们会考虑给字段添加索引呢?数据量庞大

视图

视图的作用:

  1. 简化复杂查询:把多表关联、分组统计等复杂 SQL 封装成视图,后续查数据只需SELECT * FROM 视图名,不用重复写复杂 SQL;
  2. 数据安全:可以只给用户暴露视图(比如只显示学生姓名、系别,隐藏年龄、电话等敏感字段),不直接暴露源表;
  3. 数据抽象:屏蔽表结构的细节,用户只需关注需要的字段,不用关心底层表的关联逻辑。
    ①虚表,是从一个或几个基本表(或视图)导出的表;
    ②只存放视图的定义,不存放视图对应的数据;

◆创建视图:create view <视图名> AS <子查询> [with check option];
◆删除视图:DROP VIEW <视图名>;

权限

在MySQL中使用GRANT关键字为用户设置权限。只有拥有GRANT权限,才能执行GRANT语句。

全部权限:all priviliges
所有用户:public
所有数据库:*.*
March数据库的Student表:March.Student

例1(权限授予):把查询Student表权限授给用户U1。

1
grant select on Student to U1;

例2(传播权限):把查询Student表和修改学生学号的权限授给用户U4 ,并允许他再将此权限授予其他用户。

1
grant update(Sno), select on Student to U4 with grant option;

例3(查看权限):查看tom用户的权限。

1
show grant for 'tom'@'localhost';

例4(创建登录用户、收回权限):创建用户cuit,密码123456。现有数据表books,将所有权限赋给用户CUIT。然后收回insert 权限。

1
2
3
4
5
6
7
8
9
create user 'cuit'@'localhost' identified by '123456';

grant all priviliges
on books
to 'cuit'@'localhost';

revoke insert
on books
from 'cuit'@'localhost';

例5(修改用户名和密码,删除用户):修改用户账号tempuser的密码为123456。修改普通用户U1的用户名为U2。最后删除U2。

1
2
3
SET PASSWORD FOR tempuser@localhost= '123456';
rename uesr 'U1'@'localhost' to 'U2'@'localhost';
drop user 'U2'@'localhost';

视图+授权:常用的安全性控制方法

断言

断言是数据库级别的自定义完整性约束,作用是强制整个数据库(或多个表)满足某个业务规则 —— 它和CHECK约束的核心区别是:
CHECK:只约束单个表的字段 / 行数据;
◆断言:可约束多个表之间的关联规则(也可约束单表),是更通用、更强大的完整性规则。

创建断言:create assertion <断言名> check(约束规则);
删除断言:drop assertion <断言名>

例:要求任意学生的选课门数不能超过 5 门(涉及 Student 和 SC 表关联):

1
2
3
4
5
6
7
8
CREATE ASSERTION Assert_Max_Course
CHECK (
NOT EXISTS (
SELECT * FROM SC
GROUP BY Sno
HAVING COUNT(*) > 5 -- 选课数>5的学生
)
);

理解:如果有学生选课数超过 5 门,断言约束失败,数据库会拒绝导致该结果的操作(比如插入第 6 门选课记录)。

维度 断言(Assertion) CHECK 约束
作用范围 数据库级(多表 / 单表) 表级(仅当前表)
约束对象 可关联多个表的规则 仅当前表的字段 / 行
语法灵活性 支持复杂子查询、聚合函数 仅支持单表行级逻辑(部分数据库不支持子查询)
数据库支持 仅部分数据库支持(如 Oracle),MySQL 不支持 大部分数据库支持(MySQL 8.0 + 生效)
性能 开销高(需检查全库数据) 开销低(仅检查当前行)

触发器

触发器是数据库自动执行的一段 SQL 逻辑,当对表执行INSERT/UPDATE/DELETE操作时,触发器会被 “触发”,自动执行预设的 SQL 语句。

例:假设我们有一个 orders 表,我们希望在订单状态更新时,将状态变化记录到 order_logs表中。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
delimiter //
-- 1. 创建触发器,命名为after_order_update
CREATE TRIGGER after_order_update
-- 2. 触发时机和事件:更新orders表之后触发
AFTER UPDATE ON orders
-- 3. 触发范围:行级触发器(每更新一行订单,就触发一次)
FOR EACH ROW
-- 4. 触发器要执行的逻辑开始
BEGIN
-- 5. 往订单日志表插入数据
INSERT INTO order_logs(order_id, old_status, new_status, changed_at)
-- 6. 插入的值对应:
VALUES (OLD.id, OLD.status, NEW.status, NOW());
-- 7. 触发器逻辑结束
END
//
delimiter ;

NOW()是MySQL 内置函数,获取当前系统时间(作为日志的 “状态变更时间”);

MySQL 不允许直接修改现有的触发器。如果需要修改触发器,通常的做法是先删除旧触发器,然后重新创建一个新的触发器。

数据库设计

关系模式由五部分组成,是一个五元组:R(U, D, DOM, F)。其中R是关系名,U是属性集,D是域集,DOM是映射,F是函数依赖。三元组:R<U,F>。

完全依赖(Sno, Cno) → Grade(成绩完全依赖于 “学号 + 课程号”,只知道学号或只知道课程号,都无法确定成绩)。
部分依赖(Sno, Cno, Sname)(姓名只依赖于学号,不依赖于课程号,属于 “部分依赖”)—— 这是设计表时要避免的(违反第二范式)。
传递依赖Sno → SdeptSdept → Dname(系名),则Sno → Dname(系名传递依赖于学号)—— 违反第三范式,也是设计时要避免的。

在关系型数据库中,关于数据表设计的基本原则、规则就称为范式

  • 第一范式(1NF):要求任何一张表必须有主键,每一个字段原子性不可再分
  • 第二范式(2NF):要求所有非主键字段完全依赖主键,不要产生部分依赖。
  • 第三范式(3NF):要求所有非主键字段直接依赖主键,不要产生传递依赖。

    第三范式(3NF)通常被认为在性能、拓展性和数据完整性方面达到了最好的平衡。数据库设计最重要的是看需求跟性能,需求性能>表结构。所以不能一味的去追求范式建立数据库。

  • 巴斯范式(BCNF)
  • 第四范式(4NF)
  • 第五范式(5NF ,又称完美范式), 级别最高。

    越⾼的范式数据库冗余越⼩。按照以上范式设计数据库表,可以避免表中数据的冗余,空间的浪费。

◆数据库设计的基本步骤:

存储过程是数据库中预编译、可重复执行的 SQL 代码块,可以理解为数据库层面的“函数”或“脚本”——它将一组复杂的 SQL 操作(查询、插入、更新、删除、循环、判断等)封装成一个命名实体,存储在数据库服务器中,后续通过“调用”即可重复执行,无需每次重新编写完整 SQL。

创建存储过程:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
DELIMITER //
-- 创建存储过程
CREATE PROCEDURE COMPAR (
IN K1 INTEGER, -- 输入参数1:整数
IN K2 INTEGER, -- 输入参数2:整数
OUT K3 CHAR(6) -- 输出参数:结果
)
BEGIN
IF K1 > K2 THEN
SET K3 = '大于';
ELSEIF K1 = K2 THEN
SET K3 = '等于';
ELSE
SET K3 = '小于';
END IF;
END // -- 用//结束存储过程定义
DELIMITER ;

显示存储过程状态信息:show procedure status like ‘COMPAR’;
显示存储过程创建信息:show create procedure COMPAR;

声明局部变量必须使用declare语句。局部变量必须在存储过程的开头就声明,声明完后,可以在声明它的BEGIN…END语句块中使用该变量,其他语句块中不可以使用它。

游标是一种能从包括多条数据记录的结果集中每次提取一条记录的机制。游标用于对查询数据库所返回的记录进行遍历时,游标充当指针的作用,一次只指向一行,而通过控制游标的移动,能遍历结果中的所有行,以便进行相应的操作。
◆声明游标:declare 游标名称 cursor for 结果集(select语句)
◆打开游标:OPEN 游标名称
◆提取数据:FETCH 游标名称 INTO 变量列表
◆关闭游标:CLOSE 游标名称