龙空技术网

MySQL存储过程

音视频开发老舅 109

前言:

现时兄弟们对“mysql储存文件”大体比较注意,各位老铁们都想要知道一些“mysql储存文件”的相关资讯。那么小编在网上搜集了一些有关“mysql储存文件””的相关文章,希望你们能喜欢,咱们快快来学习一下吧!

准备工作,新建名为students的数据,三张表分别是student,courses,stu_cou,并创建外键约束,级联删除更新,插入数据。

/*创建数据库*/create database if not EXISTS students character set utf8 collate utf8_general_ci;/*创建表*/use students;create table if not EXISTS student(    stuID  int(5)  not null primary key,    stuName  varchar(50)  not null,    stuSex CHAR(10),    stuAge smallint);CREATE TABLE if not EXISTS courses(         couID int  not null primary key auto_increment COMMENT '学号',         couName varchar(50) not null DEFAULT('大学英语'),         couHours  smallint UNSIGNED COMMENT '学时',         couCredit  float DEFAULT(2) COMMENT '学分')ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE  utf8mb4_0900_ai_ci;CREATE TABLE if not EXISTS stu_cou(         ID int not null primary key auto_increment,         stuID int(5)  not null  COMMENT '学号',         couID int  not null  COMMENT '课程编号',         time timestamp not null DEFAULT(now())); /*添加外键约束*/ alter table stu_cou add CONSTRAINT fk_stuid foreign key(stuID) REFERENCES student(stuID) ON UPDATE CASCADE ON DELETE CASCADE ; alter table stu_cou add CONSTRAINT fk_couid foreign key(couID) REFERENCES courses(couID) ON UPDATE CASCADE ON DELETE CASCADE ;  /*插入数据*/ insert into student(stuID,stuName,stuSex,stuAge) values(1001,'张三','男',19),(1002,'李四','男',18),(1003,'王五','男',18),(1004,'黄丽丽','女',18),(1005,'李晓辉','女',19),(1006,'张敏','女',18); insert into student VALUES(1007,'五条人','男',20),(1008,'胡五伍','女',19); insert into courses(couID,couName,couHours,couCredit) values(50,'大学英语',64,2),(60,'计算机基础',78,2.5),(70,'Java程序设计',108,6),(80,'数据库应用',48,2.5); insert into stu_cou(stuID,couID) values(1001,50),(1001,60),(1001,70),(1001,80),(1002,50),(1002,60),(1002,70),(1002,80),(1003,50),(1003,60),(1003,70),(1003,80),(1004,50),(1004,60),(1004,70),(1004,80),(1005,50),(1005,60),(1005,70),(1005,80),(1006,50),(1006,60),(1006,70),(1006,80);alter table stu_cou add COLUMN grade FLOAT null;UPDATE stu_cou set grade=(SELECT FLOOR(50 +RAND() * 50));alter table student add COLUMN stuColleage varchar(100) null;update student set stuColleage='大数据学院' where stuID BETWEEN 1001 and  1003;update student set stuColleage='物流学院' where stuID BETWEEN 1004 and  1006;update student set stuColleage='康养学院' where stuID BETWEEN 1007 and  1008;alter table courses add COLUMN couColleage varchar(50) null;update courses set couColleage='通识教育学院' where couName='大学英语';update courses set couColleage='通识教育学院' where couName='计算机基础';update courses set couColleage='大数据学院' where couName='Java程序设计';update courses set couColleage='大数据学院' where couName='数据库应用';insert into courses values(90,'大学体育',56,1.5,'通识教育学院'),(100,'Android程序设计',92,5,'大数据学院'),(101,'大学物理',48,2,'通识教育学院');insert into stu_cou(stuID,couID,grade) values(1007,50,86),(1007,60,71),(1008,70,56),(1008,80,63); insert into student VALUES(1009,'曾小小','男',17,'物流学院'),(1010,'项XXX','女',21,'大数据学院');/*视图部分*/create view `查询所有大数据学院学生`asselect * from student where stuColleage='大数据学院'with check option;create view `查询学生姓名,课程名称和分数`asSELECT stuName as '姓名',couName as '课程名称',grade as '分数' from student s INNER JOIN stu_cou sc on s.stuID=sc.stuID INNER JOIN courses c on c.couID=sc.couIDwith check option;alter view `查询所有大数据学院学生`(`学号`,`姓名`,`性别`,`学院`)asselect stuID,stuName,stuSex,stuColleage from student where stuColleage='大数据学院';create view `查询大数据学院学生的姓名,课程名称,分数和学院名称`asselect a.`姓名`,b.`课程名称`,b.`分数`,a.`学院` from `查询所有大数据学院学生` a inner join `查询学生姓名,课程名称和分数` b on a.`姓名`=b.`姓名`with check option;alter view `查询所有大数据学院学生`(`学号`,`姓名`,`性别`,`学院`)asselect stuID,stuName,stuSex,stuColleage from student where stuColleage='大数据学院'with check option;create view `查询学生表中男女同学的人数`(`性别`,`人数`)asselect stuSex,count(stuID)  from student GROUP BY stuSex;create view `查询大数据学院男同学的年龄`(`学号`,`姓名`,`性别`,`年龄`,`学院`)asselect stuID,stuName,stuSex,stuAge,stuColleage from student where stuSex='男' and stuColleage='大数据学院';
1.存储过程的语法

可以使用 CREATE PROCEDURE 语句创建存储过程,语法格式如下:

CREATE PROCEDURE <过程名> ( [过程参数[,…] ] ) <过程体>

[过程参数[,…] ] 格式

[ IN | OUT | INOUT ] <参数名> <类型>

语法说明如下:

1) 过程名

存储过程的名称,默认在当前数据库中创建。若需要在特定数据库中创建存储过程,则要在名称前面加上数据库的名称,即 db_name.sp_name。

需要注意的是,名称应当尽量避免选取与 MySQL 内置函数相同的名称,否则会发生错误。

2) 过程参数

存储过程的参数列表。其中,<参数名>为参数名,<类型>为参数的类型(可以是任何有效的 MySQL 数据类型)。当有多个参数时,参数列表中彼此间用逗号分隔。存储过程可以没有参数(此时存储过程的名称后仍需加上一对括号),也可以有 1 个或多个参数。

MySQL 存储过程支持三种类型的参数,即输入参数、输出参数和输入/输出参数,分别用 IN、OUT 和 INOUT 三个关键字标识。其中,输入参数可以传递给一个存储过程,输出参数用于存储过程需要返回一个操作结果的情形,而输入/输出参数既可以充当输入参数也可以充当输出参数。

需要注意的是,参数的取名不要与数据表的列名相同,否则尽管不会返回出错信息,但是存储过程的 SQL 语句会将参数名看作列名,从而引发不可预知的结果。

本文福利, 免费领取C++学习资料包、技术视频/代码,1000道大厂面试题,内容包括(C++基础,网络编程,数据库,中间件,后端开发,音视频开发,Qt开发)↓↓↓↓有需要的可以进企鹅裙927239107领取哦~↓↓

3) 过程体

存储过程的主体部分,也称为存储过程体,包含在过程调用的时候必须执行的 SQL 语句。这个部分以关键字 BEGIN 开始,以关键字 END 结束。若存储过程体中只有一条 SQL 语句,则可以省略 BEGIN-END 标志。

在存储过程的创建中,经常会用到一个十分重要的 MySQL 命令,即 DELIMITER 命令,特别是对于通过命令行的方式来操作 MySQL 数据库的使用者,更是要学会使用该命令。

在 MySQL 中,服务器处理 SQL 语句默认是以分号作为语句结束标志的。然而,在创建存储过程时,存储过程体可能包含有多条 SQL 语句,这些 SQL 语句如果仍以分号作为语句结束符,那么 MySQL 服务器在处理时会以遇到的第一条 SQL 语句结尾处的分号作为整个程序的结束符,而不再去处理存储过程体中后面的 SQL 语句,这样显然不行。

为解决以上问题,通常使用 DELIMITER 命令将结束命令修改为其他字符。语法格式如下:

DELIMITER $$

语法说明如下:

$$ 是用户定义的结束符,通常这个符号可以是一些特殊的符号,如两个“?”或两个“¥”等。当使用 DELIMITER 命令时,应该避免使用反斜杠“\”字符,因为它是 MySQL 的转义字符。

注意:DELIMITER 和分号“;”之间一定要有一个空格。在创建存储过程时,必须具有 CREATE ROUTINE 权限。

例1:创建一个名为ShowStu的存储过程,查询student表的内容。

delimiter // create PROCEDURE ShowStu()beginselect * from student;end//delimiter ;
2.存储过程中变量的使用

存储过程中的变量分为两种:局部变量和用户变量。

(1)局部变量

定义在存储过程中的变量,只能在存储过程内部使用,定义在存储过程开始的位置,语法:declare 变量名称 数据类型 [default 默认值]。

给变量赋值,set 变量名=表达式值[,变量名=表达式...];

如:declare sname varchar(50) default '张三'; set sname='李四';

例2:创建一个名为 proc_test2存储过程:计算输入参数的平方与输入参数/2之和。

create procedure proc_test2(in a int,out r int)beginDECLARE X INT DEFAULT 0;  #定义X int类型 默认值为0DECLARE Y INT DEFAULT 0;   #定义Y int类型 默认值为0SET X=a*a;SET Y=a/2;SET r=X+Y; end;call proc_test2(5,@r);select @r;

(2)用户变量

用户变量相当于全局变量,定义的用户变量可以通过"select @attrname from dual"进行查询。

在存储过程中使用select.....INTO.....给变量赋值。

注意:因为用户变量相当于全局变量,可以在SQL指令以及多个存储过程中共享,在开发中建议尽量少使用用户变量。用户变量过多会导致程序不易理解,难以维护。

3.存储过程的参数

MySQL中存储过程的参数一共有三种:in/out/inout

(1)IN输入参数

IN 输入参数:表示调用者向过程传入值(传入值可以是字面量或变量),默认是IN输入参数,如果不填写,就是默认的IN输入参数。

例3:创建一个名为GetNameByStu的存储过程,用于查询指定姓名的学生信息。

delimiter // create PROCEDURE GetNameByStu(in name varchar(50))beginselect * from student where stuName=name;end//delimiter ;

调用存储过程:call sp_name[(传参)];

call GetScoreByStu('李四');

(2)OUT输出参数

OUT 输出参数:表示过程向调用者传出值(可以返回多个值)(传出值只能是变量)。

例4:创建一个名为GetIDByName的存储过程,用于查询指定姓名的学生学号。

delimiter // create PROCEDURE GetIDByName(in name varchar(50),out id int)beginselect stuID into id from student where stuName=name;end//delimiter ;call GetIDByName('王五',@sid);select @sid;

输出的时候,需要在存储方法中指定,并@变量名,最后才能让这个变量接收到数值

其次输出参数的定义的时候,也和输入参数一样的,out 参数名 类型(长度)

例5:创建一个名为GetIDAndHoursByName的存储过程,用于查询指定课程名称的课程编号和课程学时。

delimiter // create PROCEDURE GetIDAndHoursByName(in name varchar(50),out id int,out hours int)beginselect couID,couHours into id,hours from courses where couName=name;end//delimiter ;call GetIDAndHoursByName('大学英语',@id,@hours);select @id;select @hours;

内部接收的时候就需要使用 into 变量名,变量名……

注意:也就是说,在存储过程中使用out声明输出参数,在内部视图into 进行赋值之后,最后在调用存储的时候需要在里面自定义一个变量进行接收 但是必须要 使用@变量名

(3)INOUT修改传入参数值

inout 表示从外部传入的参数经过修改后可以返回的变量,既可以使用传入变量的值也可以修改变量的值(即使函数执行完)

例6:创建一个名为GetSalaryByName的存储过程,传入学生名字,使用“-”拼接学号,并传入一个月的薪水值,输出年薪。

delimiter //create PROCEDURE GetSalaryByName(inout sname varchar(50) ,inout salary float)beginselect concat(stuID,"-",stuName) into sname from student where stuName=sname;set salary=salary*12;end//delimiter ;set @sname='王五';set @salary=4000.5;call GetSalaryByName(@sname,@salary);select @sname;select @salary;

相对于,如果我们使用inout关键词,这个参数可以作为输入参数,也可以作为输出参数,输出参数时候,可以在内部的语句进行修改,然后覆盖原来的值,最后调用的时候可以定义一样的变量名,也可以不一样。

in 输入参数,意思说你的参数要传到存过过程的过程里面去,在存储过程中修改该参数的值不能被返回out 输出参数:该值可在存储过程内部被改变,并向外输出inout 输入输出参数,既能输入一个值又能传出来一个值

4.存储过程中的流程控制

(1)分支控制语句

单分支控制语句:if 条件 then 语句列表 end if ;

多分支控制语句:

if 条件 then 语句列表

else if 条件 then 语句列表

else if 条件 then 语句列表

...

else 语句列表

end if ;

例7:创建一个名weekchoose的存储过程,使用多分支控制语句实现传入整型数字0,1,2,输出周日,周一,周二,如果传入其他数字则输出无效日期。

delimiter //create PROCEDURE `weekchoose`(in `day` int)BEGINif `day`=0 THEN  select '星期天';elseif `day`=1 THEN  select '星期一';elseif `day`=2 THEN  select '星期二';ELSE  select '无效日期';end if;end//delimiter ;call weekchoose(2);

例:向student表中插入一条信息,判断学号是否存在,如果存在则提示“学号已存在,不能添加”,否则向数据库添加一条数据,提示“数据添加成功”

DELIMITER $$CREATE PROCEDURE `InsertTostudent`(IN stu_id int,IN stu_name varchar(20),OUT s_result VARCHAR(20))    BEGIN       -- 声明一个变量 用来决定学号是否已经存在       DECLARE s_count INT DEFAULT 0;       -- 验证这么名字是否已经存在       SELECT COUNT(*) INTO s_count FROM student WHERE `stuID` = stu_id;           IF s_count = 0 THEN            INSERT INTO student(`stuID`, `stuName`) VALUES(stu_id, stu_name);         SET s_result = '数据添加成功';       ELSE                SET s_result = '学号已存在,不能添加';                SELECT s_result;       END IF;    END$$DELIMITER;call InsertTostudent(1010,'李晓红',@result);SELECT @result;call InsertTostudent(1011,'李晓红',@result);SELECT @result;
条件控制语句case:

case

when 条件值 then 语句列表

[when 条件值 then 语句列表]

[else 语句列表]

end case;

例8:同例7,使用case条件控制语句实现。

delimiter //create PROCEDURE `weekchoose2`(in `day` int)BEGINcase `day`when 0 THEN  select '星期天';when 1 THEN  select '星期一';when 2 THEN  select '星期二';ELSE  select '无效日期';end case;end//delimiter ;call weekchoose2(2);

(2)while循环语句

首先判断条件是否成立。如果成立,则执行循环体

[label:] WHILE 条件 DO

语句列表

END WHILE [label]

label为标号,用于区分不同的循环,可省略,用在begin、repeat、while 或者loop 语句前。

例9:使用while循环实现传入小于0的整数i,输出i+1到10的和。

delimiter //CREATE PROCEDURE `sum`(in i int,out sum int)BEGIN  set sum=0;while i<10 DO  set i=i+1;  set sum=sum+i;end while;end//delimiter ;call `sum`(0,@s);select @s;

例10:在students数据库中创建一个名为test的表,字段为id int PRIMARY key,tname varchar(50) not null,time TIMESTAMP DEFAULT now(),使用while循环向test表中插入10万条数据。

use students;create table test(id int PRIMARY key,tname varchar(50) not null,time TIMESTAMP DEFAULT now());delimiter //create PROCEDURE `InsertTotest`()BEGINDECLARE i int DEFAULT 1;while i<=100000 DO   insert into `students`.`test`(id,tname) values(i,'张三');   set i=i+1;end while;end//delimiter ;call InsertTotest();

(3)LOOP循环语句

[label:] LOOP

语句列表

END LOOP [label] ;

执行过程中可使用 LEAVE语句或者ITEREATE来跳出循环,也可以嵌套IF等判断语句。

LEAVE 语句效果对于Java中的break,用来终止循环;

ITERATE语句效果相当于Java中的continue,用来跳过此次循环。进入下一次循环。且ITERATE之下的语句将不在进行。

(4)REPEAT循环语句

先执行循环操作再判断循环条件

#与Java的do-while循环语句类似

[label:] REPEAT

语句列表

UNTIL 条件

END REPEAT [label]

5.存储过程的管理

(1)显示存储过程

show PROCEDURE STATUS;

显示特定的存储过程

show PROCEDURE STATUS where db='students' and name like '%Get%';

(2)显示存储过程的源码

show create PROCEDURE `GetIDByName`;

(3)删除存储过程

drop procedure 存储过程名称;

总结

标签: #mysql储存文件 #mysql调用存储过程传参 #mysql 执行存储过程的命令 #mysqlselect存储过程 #mysql存储过程delimiter