​    Mysql性能调优(三)    ​

转:

​Mysql性能调优(三)​

 

 

 

前言

  最近的文章均是给大家介绍mysql的性能优化,前两篇文章我们分别介绍了索引的相关知识,主要包括:索引的基本概念、引用索引的优缺点、索引的底层结构、索引的分类以及应用索引的设计原则及其语法。接下来的文章又介绍了视图以及触发器,分别介绍视图以及触发器的概念、创建、修改以及查看和删除的相关内容。

  本文将给大家介绍存储过程与存储函数的相关内容。这里主要包括存储过程的基本概念、创建、调用、删除存储过程,另外还介绍了在mysql中变量的申明以及赋值、应用。最后将给大家介绍mysql中存储过程中的三种循环结构。并且,给大家介绍游标的相关内容。

  首先给大家介绍存储过程的相关内容。

一、存储过程

1、存储过程与存储函数概述

  存储过程和函数是事先经过编译并存储在数据库中的一段SQL语句集合,调用存储过程和函数可以简化应用开发人员的很多工作,减少数据在数据库和应用服务器之间的传输,对于提高数据处理的效率是由好处的。

  其实存储过程和存储函数最关键的区别在于:函数必须有返回值,而存储过程没有。

  • 函数:是一个有返回值的过程;
  • 过程:是一个没有返回值的函数;

2、创建存储过程

  接下来给大家介绍存储过程的创建语法。

create procedure procedure_name([proc_parameter[,...]])begin
--SQL语句end;


 

  我们通过一个案例来具体说明存储过程的创建。方便大家更好的理解存储过程的语法。

delimiter $create procedure pro_test1()begin
select 'hello mysql';end $delimiter ;


 

  这里需要我们注意的是:我们在案例中用到了一个关键字——“delimiter”,该关键字用来声明sql语句的分隔符。这个关键字其实就是告知mysql解释器,该命令是否已经结束了,mysql是否可执行了。一般在默认情况下:delimiter是;。在命令行客户端中,如果有一行命令以分号结束,那么回车后,mysql将会执行该命令。

3、调用存储过程

  我们创建好存储过程之后,可以再mysql中调用存储过程,调用语法如下:

call procedure_name()


 

4、查看存储过程

  我们在调用存储过程之后,就可以在MySQL中查看存储过程。以下就是存储查看语句的如下:

--首先我们查询db_name数据库中的所有的存储过程;select name from mysql.proc where db = 'db_name';--查询存储过程的状态信息show procedure status;--查询某个存储过程的定义show create procedure test.pro_test1 G;


 

5、删除存储过程

  存储过程与其他的mysql语句一样,可以创建,可以查看,当然也可以删除,接下来,我们介绍mysql中存储过程的删除,删除的语法如下:

drop procedure [if exists] sp_name;


 

6、语法

  通过前面的介绍,相信大家对存储过程有一定的了解,其实,我们学过编程的可以知道,存储过程也是可以编程的,这就意味着我们可以同样地在创建存储的过程也可以使用我们常见的变量、表达式以及控制结构,可以完成比较复杂的功能。

(1)、变量

  • declare
      我们首先给大家介绍存储过程中的变量,变量的声明用declare关键字。我们可以通过declare可以定义一个局部变量,但是该变量的作用范围只能在begin…end块中。主要的语法如下:

declare var_name[,...] type [default value]


 

  我们介绍了declare的语法,我们通过一个案例来说明declare的用法。

delimiter $create procedure pro_test2()begin
declare num int default 5;
select num+ 10;end$delimiter ;


 

  • set
      我们前面介绍了declare定义一个局部变量,接下来,我们介绍set直接赋值,可以赋常量或者赋表达式,具体的语法如下:

set var_name = expr [, var_name = expr]...


 

  我们介绍了set的语法,我们通过一个案例来说明set的用法。

delimiter $create procedure pro_test3()begin
declare name varchar(20);
set name = 'mysql';
select name;end$delimiter ;


 

  当然,我们可以通过select…into方法进行赋值操作,接下来,我们可以通过一个案例来说明用法:

delimiter $create procedure pro_test5()begin
declare countnum int;
select count(*) into countnum from city;
select countnum;end$delimiter ;


 

(2)、if条件判断

  前面主要介绍了存储过程中的变量,主要包括定义一个变量declare以及赋值关键字set。接下来,给大家介绍if条件的判断语句。语法结构如下:

if search_condition then statement_list [elseif search_condition then statement_list]
[else statement_list]end if


 

  接下来我们通过一个案例来呈现if条件判断语句的实现,为了方便大家理解,具体的案例如下:

  根据定义的身高变量,判定当前身高的所属的身材类型。

  • 180及以上 ——————> 身材高挑
  • 170-180 ——————> 标准身材
  • 170以上 ——————> 一般身材

  具体存储过程如下:

create procedure pro_test4()begin
declare height int default 175;
declare description varchar(50) default '';
if height >= 180 then set description = '身材高挑';
elseif height >= 170 and height < 180 then set description = '标准身材';
else set description = '一般身材';end if;select concat('身高', height, '对应的身材类型为:',description);end $;


 

  我们可以通过调用语句来实现存储过程,具体实现如下:

call pro_test6();


 

  具体的结果如下:

Mysql性能调优(三)_Mysql性能调优

(3)、传递参数

  前面我们也提到过,存储过程也可以编程,也有函数的,我们学过编程语言的,无论是java也好还是c语言也罢,其中函数均可以传参数的。具体语法的格式如下:

create procedure procedure_name([in/out/inout]参数名 参数类型)


 

  根据我们刚才介绍的传递参数的语法中,有in、out以及inout,因此,我们接下来给大家介绍他们三者的含义:

  • in:该参数可以作为输入,也就是需要调用方传入值,这里我们如果不特殊指定就是默认值。
  • out:该参数作为输出,也就是该参数可以作为返回值
  • inout:既可以作为输入参数,也可以作为输出参数

  还是之前我们提到的身高问题来分别为大家实现in、out与inout的使用方法,由于前面的我们提到的身材类型,因此,就不在重新描述。

  首先,让我们用in来实现身高问题,具体的实现语句如下:

create procedure pro_test5(in height int)begin
declare description varchar(50) default '';
if height >= 180 then set description = '身材高挑';
elseif height >= 170 and height < 180 then set description = '标准身材';
else set description = '一般身材';end if;select concat('身高', height, '对应的身材类型为:',description);end $;


 

  接下来让我们out输出实现身高问题

create procedure pro_test5(in height int, out description varchar(100))begin
declare description varchar(50) default '';
if height >= 180 then set description = '身材高挑';
elseif height >= 170 and height < 180 then set description = '标准身材';
else set description = '一般身材';end if;end $;


 

  接下来,我们调用这个函数

call pro_test5(168, @description)$select @description$


 

  这里需要我们注意的是在调用中出现了一个@description的关键字。接下来给大家介绍相关的知识:

  •    @description:这种变量要在变量名称前面加“@”符号,这种符号叫做用户会话变量,代表整个会话过程他都是有作用的,这个类似于全局变量一样。
  •   @@global.sort_buffer_size:这种在变量前加上“@@”符号,叫做系统变量。

(4)、case结构

  前面介绍了if条件判断,接下来我们介绍case结构判断。具体的语法结构如下:

--**方法一**:case case_value when when_value then statement_list [when when_value then statement_list]...
[else statement_list]end case;--方法二:case
when search_condition then statement_list [when search_condition then statement_list]...
[else statement_list]end case


 

  以上是case的基本语法,接下来我们通过一个案例来说明case的用法;具体的案例如下:

  给定一个月份,然后计算出所在的季度

create procedure pro_test7(mon int)begin
declare result varchar(10);
case
when mon >=1 and mon <= 3 then
set result = '第一季度';
when mon >=4 and mon <= 6 then
set result = '第二季度';
when mon >=7 and mon <= 9 then
set result = '第三季度';
else
set result = '第四季度';
end case;
select concat('传递的月份为:', mon, ',计算出的结果为:', result) as content;end$


 

(5)、while循环

  前面介绍了条件格式;其中包括我们常见的if语句和case语句。接下来,给大家介绍循环语句,其中主要包括while、repeat和loop函数。首先给大家介绍while循环,具体语法如下:

while search_condition do
statement_listend while;


 

  接下来我们通过一个案例来说明case的用法;具体的案例如下:

  计算从1加到n的值 --累加

  具体的实现如下:

create procedure pro_test8(n int)begin
declare total int default 0;
declare num int default 1;
while num <= n do
set total = total + num;
set num = num + 1;
end while;
select total;end$


 

(6)、repeat结构

  我们刚才为大家介绍了while循环,接下来给大家介绍repeat结构。repeat结构是有条件的循环控制语句,当满足条件的时候退出循环。接下里给大家介绍repeat与while两种循环的结构的区别:

  • while是满足条件才执行的
  • repeat是满足条件就退出循环

  具体的语法如下:

repeat 
statement_lsit
until search_conditionend repeat;


 

  接下来我们通过一个案例来说明repeat的用法;这个案例和前面的案例是一个样的,因此实现如下:

create procedure pro_test9(n int)begin
declare total int default 0;
repeat
set total = total + n;
set n = n - 1;
until n = 0
end repeat;
select total;end$


 

(7)、loop语句

  我们介绍最后一种循环语句loop函数,loop可以实现简单的循环,退出循环的条件使用其他语句的定义,通常可以使用leave语句实现,具体的语法实现如下:

[begin_label:] LOOP
statement_listend loop[end_label]


 

  这里需要我们注意的是:如果不在statement_list中增加退出循环的语句,那么loop语句可以用来实现简单的死循环。

(8)、leave语句

  我们刚才介绍了loop循环语句,也提到了loop循环结构要与leave语句搭配使用,其中的leave语句是用来退出loop中的循环的。一般情况,要和begin…end或者循环一起使用。接下来我们用loop和leave的简单例子,具体实现如下:

create procedure pro_test10(n int)begin
declare total int default 0;
c:loop
set total = total + n;
set n = n - 1;
if n <= 0 then
leave c;
end if;
end loop c;
select total;end$


 

(9)、游标/光标

  我们前面介绍了三种循环结构,下来给大家介绍一种特别重要的数据类型:游标。游标是用来存储查询结果集的数据类型,在存储过程和函数中可以使用光标对结果进行循环处理。光标的使用包括光标的声明、open、fetch和close,其中的语法如下:

--声明光标:declare cursor_name cursor for select_statement;--open光标open cursor_name;--fetch光标fetch cursor_name into var_name [, var_name]...--close光标close cursor_name;


 

  介绍完游标的基本语法的时候,接下来,我们通过一个案例来具体实现游标的应用。首先我们初始化的脚本,即首先创建一张表,并且插入一些数据。

create table emp(
id int(11) not null auto_increment,
name varchar(50) not null comment '姓名',
age int(11) comment '年龄',
salary int(11) comment '薪水',
primary key(`id`))engine=innodb default charset=utf8;insert into emp(id, name, age, salary) values (null, 'stefan', 16, 28000),(null, 'napoleon', 26, 18000),(null, 'porrty', 18, 8000),(null, '张三', 26, 2600);


 

  建立好表也插入了数据,接着我们可以查看emp表中的数据,并逐行获取进行展示。

create procedure pro_test11()begin
declare e_id int(11);
declare e_name varchar(50);
declare e_age int(11);
declare e_salary int(11),
declare emp_result cursor for select * from emp;
declare exit handler for not found set has_data=0;
open emp_result;
repeat
fetch emp_result into e_id, e_name, e_age, e_salary;
select concat('id=', e_id, ',name=',e_name, ', age=', e_age, ',薪资为:', e_salary);
until has_data = 0
end repeat;
close emp_result;end$


 

  我们的存储过程已经全部介绍完了,存储过程比较重要,也是一个很高级的写法,能够希望大家很好的掌握,接下来,给大家介绍存储函数。

二、存储函数

  前面介绍了存储过程,接下来我们介绍存储函数的语法结构:

create function function_name([param type ...])returns typebegin
...end;


 

  我们接下来定义一个存储函数,获取满足条件(city)的总记录数。接下来实现如下:

delimiter $create function count_city(countryId int)returns intbegin
declare cnum int;
select count(*) into cnum from city where country_id = countryId;
return cnum;end$delimiter ;


 

  接下来,我们调用该存储函数,具体实现如下:

select count_city(1);select count_city(2);


 

  由于存储函数比较简单,因此,我们在介绍的时候比较简单。

总结

  我们最近的文章均会给大家介绍mysql的性能,前两篇文章我们分别介绍了索引的相关知识以及视图以及触发器,本文给大家介绍了存储过程与存储函数的相关内容。存储过程的介绍主要包括:基本概念、创建、调用、删除存储过程,另外还介绍了在mysql中变量的申明以及赋值、应用,另外还给大家介绍mysql中存储过程中的三种循环结构。其次给大家介绍游标的相关内容。最后,我们介绍了存储函数的语法。因此,mysql是很重要的一个技能,几乎计算机中的每个岗位都需要一个mysq技能,因此,需要我们特别的掌握。生命不息,奋斗不止,我们每天努力,好好学习,不断提高自己的能力,相信自己一定会学有所获。加油!!!

转:

Mysql性能调优(三)