数据库第三章

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
CREATE SCHEMA `school`
DEFAULT CHARACTER SET utf8
COLLATE utf8_bin;

-- CREATE DATABASE `school`;
-- Drop DATABASE `school`;

use school;
create table `student`(
`sno` char(10) not null primary key,
`sname` varchar(45) not null ,
`sage` int null default 18,
`sdept` varchar(45)
)COMMENT = '学生信息表';
drop table student;

create table course(
cno char(4) not null primary key,
cname varchar(45) not null,
-- 列级约束
cpno char(4) references cno,
credit tinyint
);
-- drop table course;

create table sc(
sno char(10),
cno char(4),
score int,
-- 表级约束
primary key (sno,cno),
-- 约束限制:constraint关键字
constraint `fk_sno` foreign key(sno) references student(sno),
foreign key(cno) references course(cno)
-- 类型要一致,宽度要一致
);
drop table sc;

问题:Error Code: 1822. Failed to add the foreign key constraint. Missing index for constraint 'fk_sno' in the referenced table 'student'

MySQL报这个错时去检查外键设置!!!这个外键是不是另外一个表的主键
设置外键的时候需要注意以下几点:
1)外键是用于两个表的数据之间建立连接,可以是一列或者多列,即一个表可以有一个或多个外键。
2)这个表里面设置的外键必须是另外一个表的主键!
3)外键可以不是这个表的主键,但必须和另外一个表的主键相对应(字段的类型和值必须一样)。
4)带有主键的那张表称为父表,含外键的是子表,必须先删除外键约束才能删除父表。

所以:school生成表时忘记给sno加主键了。经过搜索暂没有法子直接修改数据为主键,故删表重写QAQ

刚刚了解constraint约束,发现一个加主键的法子
alter table student add constraint pk primary key (sno);
格式为:
alter table 表格名称 add constraint 约束名称 增加的约束类型 (列名)
constraint `fk_sno` foreign key(sno) references student(sno)
没有写名字系统会默认生成名字,如:sc_ibfk_1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
1,根据内容划分
2.根据作用域、作用范围划分
域(列)完整性:
域完整性是对数据表中字段属性的约束
实体完整性在MySQL中实现:
通过主键约束和候选键约束实现的
参照完整性:
也就是说是MySQL的外键
3.根据声明语句的书写形式、约束声明的位置划分
列级约束
name varchar(20) default ‘老王’
表级约束
[constraint fk_name] foreign key(deptno) references dept(deptno) 所有的列都声明完了,再声明约束
create table emp(
empno int promary key auto_increment,
ename varchar(32not null,
deptno int,
[constraint fk_name] foreign key(deptno) references dept(deptno) – 添加外键约束
);
[]可选择内容,去掉
id、name组合值不能重复,单一重复可通过
constraint id_unique unique(id, name) – 添加复合约束

练习代码:

USE school;
CREATE TABLE t1(
#default:默认约束, 域完整性;指定某列的默认值,插入数据时候,此列没有值,则用default指定的值来填充
id INT DEFAULT 1,
#,写; : id INT DEFAULT 1;
#错误代码: 1064
#You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '' at line 2
#错误代码: 1064
#You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'name varchar(20default '老王')' at line 1
NAME VARCHAR(20) DEFAULT '老王'
);

#插入操作
INSERT INTO t1 VALUES ('haha');#未要求要全部写入
#错误代码: 1136
#Column count doesn't match value count at row 1

INSERT INTO t1(id) VALUES (3);
INSERT t1(NAME) VALUES ('haha');

#修改默认值
ALTER TABLE t1 MODIFY id INT DEFAULT 4;
ALTER TABLE t1 MODIFY NAME VARCHAR(20) DEFAULT '小白';

#删除默认值操作modify/change
ALTER TABLE t1 MODIFY id INT;
ALTER TABLE t1 CHANGE NAME NAME VARCHAR(20);

#查询内容
SELECT * FROM t1;

CREATE TABLE t2(
#not null: 非空约束,域完整性;指定某列的值不为空,在插入数据的时候必须非空 ‘’ 不等于 null, 0不等于 null
id INT NOT NULL,
NAME VARCHAR(20) NOT NULL
);

#插入操作
INSERT t2(id) VALUES (2);
#错误代码: 1364
#Field 'name' doesn't have a default value
INSERT t2(NAME) VALUES ('小花');
#错误代码: 1364
#Field 'id' doesn't have a default value
INSERT t2 VALUES (3,'小华'),(5,'小黑');

#添加not null约束
#1.建表时
#2.alter语句添加:alter…modify/change…
ALTER TABLE t2 MODIFY id INT NOT NULL;
ALTER TABLE t2 MODIFY NAME VARCHAR(20) NOT NULL;

#删除约束:alter…modify/change…
ALTER TABLE t2 MODIFY id INT;
ALTER TABLE t2 CHANGE NAME NAME VARCHAR(10);#alter完全修改内容

SELECT * FROM t2;

CREATE TABLE t3(
#unique: 唯一约束,实体完整性;指定列或者列组合不能重复,保证数据的唯一性;不能出现重复的值,但是可以有多个null;同一张表可以有多个唯一的约束
id INT UNIQUE,
NAME VARCHAR(20)
);

#插入操作
INSERT t3(id) VALUES (2);
INSERT t3(NAME) VALUES ('小花');
INSERT t3 VALUES (3,'小华'),(5,'小黑');
#内容重复输入
INSERT t3 VALUES (3,'小华'),(5,'小黑');
#错误代码: 1062
#Duplicate entry '3' for key 't3.id'

#添加约束
ALTER TABLE t3

#删除约束
ALTER TABLE t3 DROP INDEX id_unique;
DROP id ON t3;

SELECT * FROM t3;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
#SQL:结构化的查询语言
#交互式SQL,嵌入式SQL
#select 目标表达式列表
#from 目标关系列表
#where 目标条件列表 -> 条件子句
#order by 排序子句
#group by 分组子句

#一、单表查询
#一个for语句遍历所有的行
#数据库中第三种状态:除了真假,还有未知
#目标列查询 *,col1,col2
#目标表达式列表 重命名 数学表达式函数

use school;
select * from student;
select sno,sname from student;

#重命名
select sno as '学号', sname as '姓名' from student;
#as和单引号可省略,单引号使用防止字符有空格
select sno 学号,sname as '姓 名' from student;

select 2022-sage '出生年份' from student;
#不加'出生年份''2022-sage'作为列名
select 2022-sage from student;

select cno from course;
#可跟函数
select lower(cno) from course;
select upper(cno) from course;

#聚集函数/统计查询
select count(*) from student;
select count(*) as '班级人数' from student;

#单条件查询where
select sno,sname,ssex from student where ssex='女';
select sno,sname,ssex,sage from student where sage<=30 and ssex='男';
select sno,sname,ssex,sage from student where sage<=30 or ssex='男';#'男'不要加空格,虽然有些软件可以自动去两边空格,仅侥幸
select * from student where sdept='计算机系' or sdept='历史系';
#减短查询:查询集合in
select * from student where sdept in ('计算机系','音乐系','历史系');

select * from student where sage>=23 and sage<25;#[23,25)
select * from student where not sage>=23 and sage<25;
select * from student where sage between 23 and 25;#并,闭区间[23,25],多条件无法实现

#一个for语句遍历所有的行,where为真true才被选中
#数据库中第三种状态:除了真假,还有未知
select * from course;
select * from course where not cpno='C001'; #为空未被选中
select * from course where cpno!='C001';
select * from course where cpno=null;#无法比较……得到未知
select * from course where cpno is null;
select * from course where cpno is not null;#方式一
select * from course where not (cpno is null);#方式二

#只限制前三条查询:起始下标0,偏移量3(网页分页查询使用)
select * from student where ssex='男' limit 0,3;

#所有的人按系科排序(默认:升序排序asc)-> 字符集utf8 排序规则utf8_bin
select * from student order by sdept desc;
select * from student order by sdept desc, sage asc;#放最后执行
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
#单表查询的分组聚集查询
#select 目标表达式列表 from 目标关系列表 where 目标条件列表 group by 分组条件列表(方便计算) order by 排序列列表(排序所依赖的列,方便看,最后一个子句)

select * from course where cpno=null;
#where子句只认后面结果是否为真,null不管在哪是不是空和任何数据得到结果都是不知道,无法比较
select * from course where cpno is null;
select * from course where not(cpno is null);
select lower(cno),cname from course;
select * from student order by sdept asc, sage desc;

#1.coubt(*)记得元祖的数目(整个行),2.某个分量里出现的个数(某一列)
select count(*) from student;
select count(*) from student where ssex='男';
select count(ssex) from student where ssex='女';#没去重,记了两次 -> distinct
select count(distinct ssex) from student where ssex='女';
select count(distinct ssex) from student;

select * from course order by cpno asc;
#升序排列空值放最上面,可能作为最小值看待

#聚集查询/统计查询
select count(*) as '人数', max(sage) as '最大年龄', min(sage) as '最小年龄', sum(sage), avg(sage) from student;
#正常,更多都是用在分组统计
#空值统计是不在内的

select cpno, count(*) from course group by cpno;
#询问:空值怎办?是否有一个专有的分组? 分组和排序,空值都算在内 (空值作为一个具体的值也参与分组,只是计数,但不能进行计算:求平均值...)

select count(*) as '人数', max(sage) as '最大年龄', min(sage) as '最小年龄', sum(sage), avg(sage) from student where ssex='男';
select sdept, count(*) as '人数', max(sage) as '最大年龄', min(sage) as '最小年龄', sum(sage), avg(sage) from student group by sdept;
#对分组进行筛选
#where是对元祖进行筛选,having是对分组进行筛选(具体的值),无太大差别(having必须在group by后面用,可以使用聚集函数count(*)>=2)
select sdept, count(*) as '人数', max(sage) as '最大年龄', min(sage) as '最小年龄', sum(sage), avg(sage) from student group by sdept having count(*)>=2;
select sdept,avg(sage) as '平均年龄' from student where ssex='男' group by sdept having avg(sage)>=22;
#可以使用别名进行筛选,'平均年龄'>=22当成字符串和22比较 -> 平均年龄>=22
select sdept,avg(sage) as '平均年龄' from student where ssex='男' group by sdept having 平均年龄>=22;
#名字里含有空格加 ``(用于表名,列名)
select sdept,avg(sage) as '平 均 年 龄' from student where ssex='男' group by sdept having `平 均 年 龄`>=22;

#单表查询的模糊查询 like
select * from student where sname like "刘%"; # %:0个或多个字符
select * from course where cname like '%C语言%'; #对大小写敏感Cc
select * from student where sname like '诸葛_'; #一个 _ 表示一个字符
#内容就含有%和_:替代别人的功能卸载掉 \% 或 \_
select * from course where cname like '\%C语言%';
#若\也作为内容,使用\\表示内容,利用ESCAPE寻找其它字符赋予其\的功能
select * from course where cname like '1%C语言%' escape '1';
#用的比较少好,一般用正则表达式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
#多表查询
#1.连接查询
#最简单链接:笛卡尔积(交叉连接)cross join
#内连接inner join...on:一般连接,等值连接,自然连接(公共属性上的等值连接)nature join
#外连接:左外连接left join...on,右外连接right join...on,全外连接full join

#2.嵌套查询:不相关子查询(干完就跑路)、相关子查询(交错互通,内层查询都要看一下外层查询,外层查询都要看一下内层查询)
#不相关子查询(干完就跑路) in(…)
#一个值 ‘=’;多个值 ‘in''=ANY'
#sname<>"刘备" : 不包括刘备
#"> ALL" == > max 大于所有的
#"> ANY" == >min 大于某一个 P92

#3.集合查询
待续……

use school;
#单表查询 9'
#简单查询、条件查询、空值查询(is null/is not null)、
#between and、count(*) min(*),目标表达式(列名、重名、运算、函数)、
#分组查询(group by...having)、模糊查询(like,escape,"\\")、排序字句(order by...asc/desc)
#select 目标表达式列表 from 目标关系列表 where 目标条件列表(and,or,not分割) group by 分组列 order by 排序依据列+排序方式

select * from sc;
select sno from sc where cno="C003";
#找出选修C001也选修C003的同学学号
select sno,cno from sc where cno="C001" and cno="C003";#错的
(select sno,cno from sc where cno="C001") union (select sno,cno from sc where cno="C003");
select sno from sc where cno="C001" and
sno in (select sno from sc where cno="C003");
select sc.sno,sname,sc.cno,cname,grade from student,course,sc where student.sno=sc.sno and sc.cno=course.cno and sc.cno="C003";

#多表查询
#1.连接查询
select * from student,sc where student.sno=sc.sno;
select sno,sname from student,sc where student.sno=sc.sno and cno="C003";#Error Code: 1052. Column 'sno' in field list is ambiguous
select student.sno,sname from student,sc where student.sno=sc.sno and cno="C003";
select sc.sno,sname from (student inner join sc on student.sno=sc.sno) where cno="C003";

#最简单链接:笛卡尔积(交叉连接)cross join
select * from student,sc;
select * from student cross join sc;

#内连接inner join...on:一般连接,等值连接,自然连接(公共属性上的等值连接)nature join,
select * from student inner join sc;
select sc.sno,sname from (student inner join sc on student.sno=sc.sno) where cno="C003";
select * from student natural join sc;#只剩一行sno
select * from student natural join student;#Error Code: 1066. Not unique table/alias: 'student'
select * from student A natural join student B;#自己与自己自然连接,先相等再去掉一份

#外连接:左外连接left join...on,右外连接right join...on,全外连接full join
select * from student left join sc on student.sno=sc.sno;
select * from sc right join student on student.sno=sc.sno;
select * from student full join sc on student.sno=sc.sno;#Error Code: 1054. Unknown column 'student.sno' in 'on clause'
select * from student full join sc ;


#2.嵌套查询:不相关子查询(干完就跑路)、相关子查询(交错互通,内层查询都要看一下外层查询,外层查询都要看一下内层查询)
#不相关子查询(干完就跑路)
select sno,sname from student where
sno in (select cno from sc where cno="C003");

select sname from student where sdept=(select sdept from student where sname="刘备");#一个值 ‘=’;多个值 ‘in''=ANY'
select sname from student where sname<>"刘备" and sdept=(select sdept from student where sname="刘备");#sname<>"刘备" 不包括刘备
select * from student where sdept<>"计算机系" and sage>ANY (select sage from student where sdept="计算机系");
#"> ALL" == > max 大于所有的
#"> ANY" == >min 大于某一个 P92


#3.集合查询
(select sno,cno from sc where cno="C001") union (select sno,cno from sc where cno="C003");


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
#SQL查询 select
#一、单表查询
#1.目标查询 from
#2.条件查询 where
#3.分组查询 group by
#4.排序查询 order by
#二、多表查询
#1.连接查询 cross join
#2.嵌套查询
#(1)不相关子查询
#(2)相关子查询 EXISTS
#3.集合查询

use school;

select * from student;
#连接查询
select b.* from student a,student b where a.sname='刘备' and b.sname<>"刘备" and a.sdept=b.sdept;
select * from student a,student b where a.sname='刘备' and b.sname<>"刘备" and a.sdept=b.sdept;
#不相关子查询
select sdept from student where sname="刘备";
select * from student where sname<>"刘备" and sdept=(select sdept from student where sname="刘备");
#相关子查询
select * from student X where X.sname<>"刘备" and EXISTS(select * from student Y where Y.sname="刘备" and Y.sdept=X.sdept);

#EXISTS 存在谓词:只要有返回值就为真
select * from sc where sno='202006001' and cno='C003';
select sname from student where EXISTS (select * from sc where sno=student.sno and cno='C003');#m*n
select sname from student,sc where student.sno=sc.sno and cno='C003';
select sname from student where sno in (select sno from sc where cno='C003');#m+n

#最难最重要: 存在谓词表达全部和否定
select sname from student,sc where student.sno=sc.sno and cno<>'C003';#错误!!!
select sname from student where sno not in (select sno from sc where cno='C003');#m+n

select * from course where not exists(select * from sc where sno='202006001' and cno=course.cno);
select * from course where exists(select * from sc where sno='202006001' and cno=course.cno);

#查询选修了全部课程的学生的信息 等价于 不存在一门课该学生没有选修
select sno,sname from student where not exists(select * from course where not exists(select * from sc where student.sno=sc.sno and sc.cno=course.cno));
select sno,sname from student where not exists(select * from course where cpno='C003' AND not exists(select * from sc where student.sno=sc.sno and sc.cno=course.cno));
#查询选修了【202006001选修的课】全部课程的学生信息 等价于 不存在这么一门课,刘备选了而你没有选
select sno from sc A where not exists(select * from sc B where B.sno='202006001' and not exists(select * from sc C where B.cno=C.cno and A.sno=C.sno));

#查询选修了【202006001选修的课】全部课程的学生信息 等价于 不存在这么一门课,刘备选了而你没有选(distinct去重)
select distinct sno from sc A where not exists(select * from sc B where B.sno='202006001' and not exists(select * from sc C where B.cno=C.cno and A.sno=C.sno));
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
USE school;

DELIMITER $$
CREATE PROCEDURE insert_student(
p_sno CHAR(10),
p_sname VARCHAR(50),
p_sex VARCHAR(1),
p_age INT,
p_dept VARCHAR(20)
)
BEGIN
# 声明变量info,以表明插入是否成功。
DECLARE info VARCHAR(20) DEFAULT '插入成功';
# 异常处理
DECLARE CONTINUE HANDLER FOR 1062 SET info='插入失败,不能插入重复的数据';
INSERT INTO student VALUES(p_sno,p_sname,p_sex,p_age,p_dept);
SELECT info;
END $$
DELIMITER ;

SET @sno='202006012';
SET @sname='魏延';
SET @ssex='男';
SET @sage=25;
SET @sdept='计算机系';

SET @sno='202006012';
SET @sname='甄宓';
SET @ssex='女';
SET @sage=32;
SET @sdept='汉语言系';
CALL insert_student(@sno,@sname,@ssex,@sage,@sdept);
SELECT * FROM student;

#系统变量,用户自定义变量,局部变量
select @@version;

#delimiter双$符号的作用
#插入一个相同学号的同学
#插入一个超出字符限制的数据
#区别和联系
#存储过程使用call,可返回好多输出变量,作为一句话调用
#函数不用call调用,写上就可以得到值,可以作为表达式一部分
#触发器在满足特定条件下才能触发
#游标

#创建存储过程
delimiter $$
create procedure proc01()
begin
select sname,sage from student;
end $$
delimiter ;
call proc01;

#定义局部变量: 用户自定义,在begin/end块中有效
#declare var_name type [default var_value];
delimiter $$
create procedure proc02()
begin
declare tname varchar(20) default "student's name";
-- declare tname varchar(5) default "student's name";
set tname = 'Yangyang';
select tname;
end $$
delimiter ;
call proc02();
#Error Code: 1406. Data too long for column 'tname' at row 1
drop procedure proc02;

#用户变量:用户自定义,不需要提前声明,使用及声明;可在begin/end块外有效(外部也可以使用用户变量)
# @var_name
delimiter $$
create procedure proc03()
begin
set @tname = 'potato';
select @tname;
end $$
delimiter ;
call proc03();
select @tname;

#系统变量分为全局变量和会话变量
# @@global.var_name
#全局变量在MYSQL启动的时候由服务器自动将他的初始化为默认值
#会话变量在每次建立一个新的连接的时候,由MYSQL来初始化,MYSQL会将当前所有全局变量的值复制一份,来作为会话变量
#全局变量的修改会影响整个服务器,但是对会话变量的修改,只会影响到当前的会话(也就是当前的数据库连接)
#可以更改的系统变量,我们可以利用set语句进行更改
show global variables;-- 查看全局变量
select @@sort_buffer_size;-- 查看某全局变量
set @@sort_buffer_size = 50000;-- 修改全局变量的值
set global sort_buffer_size = 100000;
select @@sort_buffer_size;

#存储过程传参
#in表示传入的参数,可以传入数值或者变量,即使传入变量,并不会改变变量的值,可以内部更改,
#仅仅作用在函数范围内
delimiter $$
create procedure proc04(in miniage int,in maxage int)
begin
select * from student where sage>miniage and sage<maxage;
end $$
delimiter ;
drop procedure proc04;
call proc04(22,30);

#out表示从存储过程内部传值给调用者
delimiter $$
create procedure proc05(in in_sage int, out out_sname varchar(45))
begin
select sname into out_sname from student where sage=in_sage;
end $$
delimiter ;
call proc05(22,@out_res);
select @out_res;

#inout表示从外部传入的参数经过修改后可以返回的变量,既可以使用传入变量的值
#也可以修改变量的值(即使函数执行完)
delimiter $$
create procedure proc06(inout num int)
begin
set num = num*10;
end $$
delimiter ;
set @inout_num = 2;
call proc06(@inout_num);
select @inout_num;

#流程控制-判断
#if...then...;
#elseif...then...;
#end if;
#判断IF语句包含多个条件判断,根据结果为TURE和FALSE执行语句,与编程语言中的ifelse if
#else语法类似
delimiter $$
create procedure proc07(in score int)
begin
if score<60 then select '不及格';
elseif score>=60 and score<80 then select '及格';
elseif score>=80 and score<90 then select '良好';
elseif score>=90 and score<=100 then select '优秀';
else select '成绩错误!';
end if;
end $$
delimiter ;
set @score = 79;
call proc07(@score);

delimiter $$
create procedure proc08(in in_name varchar(45))
begin
declare var_float decimal(7,2); -- 定义局部变量,7个长度,2个小数
declare res varchar(20);
select sage into var_float from student where sname=in_name;
if var_float>25 then set res='毕业了';
else set res='在上学';
end if;
select res;
end $$
delimiter ;
call proc08('刘备');

delimiter $$
create procedure proc07(in score int)
begin
declare res varchar(45);
if score<60 then set res= '不及格';
elseif score>=60 and score<=100 then set res= '及格';
else set res= '成绩错误';
end if;
select res as '成绩结果';
end $$
delimiter ;
drop procedure proc07;
set @score=55;
call proc07(@score);

#流程控制-case
#case...
#when...then...;
#else...;
#end case;
#CASE是另一个条件判断语句,类似于编程语言中的switch语法
#语法一:当case后面的语句与when后面的语句相等时,则会执行then后面的语句,如果均不匹配则执行else
#语法二:直接写case 当when后面的条件成立则执行then后面的语句,如果都不成立,则执行else
delimiter $$
create procedure proc08(in food varchar(45),in pay_type int)
begin
case '面包'
when 1 then select '微信支付';
when 2 then select '支付宝支付';
else select '其他支付方式';
end case;
case '饮料'
when 1 then select '微信支付';
when 2 then select '支付宝支付';
else select '其他支付方式';
end case;
end $$
delimiter ;
call proc08('饮料',2);

#控制流程-循环
#循环分类:while、repeate、loop
#循环控制:leave 类似于break,跳出,结束当前所在的循环
# iteater 类似于continue,继续,结束本次循环,继续下一次

#label:while...do
#...
#if...then leave label;
#end while lable;
delimiter $$
create procedure proc09(in insertCount int)
begin
declare i int default 1;
label:while i<=insertCount do
insert into student(sno,sname) values(i,concat('user-',i));
set i=i+1;
end while label;
end $$
delimiter ;
drop procedure proc09;
call proc09(10);

delimiter $$
create procedure proc10(in delCount int)
begin
declare i int default 1;
label:while i<=delCount do
delete from student where sno=i;
if i=5 then leave label;
end if;
set i = i+1;
end while label;
end $$
delimiter ;
drop procedure proc10;
call proc10(10);
#Error Code: 1175. You are using safe update mode and you tried to update a table without a WHERE that uses a KEY column. Cannot use range access on index 'PRIMARY' due to type or collation conversion on field 'sno' To disable safe mode, toggle the option in Preferences -> SQL Editor and reconnect.
#因为MySql运行在safe-updates模式下,该模式会导致非主键条件下无法执行update或者delete命令。可以通过以下SQL进行状态查询
show variables like 'SQL_SAFE_UPDATES';
SET SQL_SAFE_UPDATES = 0;

#label:repeat
#...;
#until 条件表达式;
#end repeat label;
delimiter $$
create procedure proc11(in insertCount int)
begin
declare i int default 1;
label:repeat
insert into student(sno,sname) values(i,concat('user-',i));
set i=i+1;
until i>insertCount
end repeat label;
select '循环结束';
end $$
delimiter ;
call proc11(10);

#label:loop
# ...
# if 条件表达式 then leave label;
# end if;
# end loop label;
delimiter $$
create procedure proc12(in delCount int)
begin
declare i int default 1;
label:loop
delete from student where sno=i;
set i=i+1;
if i>delCount then leave label;
end if;
end loop label;
end $$
delimiter ;
drop procedure proc12;
call proc12(10);
#调用储存过程显示Error Code: 1305. PROCEDURE school.proc12 does not exist
#1.首先考虑是否是此储存过程当真不在,查看当前存储过程,发现存储过程存在:
#show procedure status;
# 2.此时想到是用户没有当前存储过程的调用权限,赋予存储过程权限给当前用户,此时又出现了一个错误
#GRANT ALL PRIVILEGES ON *.* TO 'root'@'%';
#ERROR 1133 (42000): Can't find any matching row in the user table
#通过查询资料发现,需要先将当前的存储过程刷新,再执行授权语句:
#FLUSH PRIVILEGES;
#GRANT ALL PRIVILEGES ON test.* TO 'root'@localhost;
#3.再执行调用此存储过程,显示成功调用