MySQL支持把几种对象存放在服务器端供以后使用。这几种对象有一些可以根据情况通过程序代码调用,有一些会在数据表被修改时自动执行,还有一些可以在预定时刻自动执行。它们包括以下几种:

1.存储函数(stored function)。返回一个计算结果,该结果可以用在表达式里。
2.存储过程(stored procedure)。不直接返回一个结果,但可以用来完成一般的运算或是生成一个结果集并传递回客户。
3.触发器(trigger)。与数据表相关联,当那个数据表被工NSERT、DELETE或UPDATE语句修改时,触发器将自动执行。
4.事件(event)。根据时间表在预定时刻自动执行。

MySQL对存储函数和存储过程的支持始于5.0.0版本,对触发器和事件的支持分别始于5.0.2版本和5.1.6版本。存储程序有以下优点和能力:

1.存储程序对象的可执行部分可以用复合语句来编写,复合语句对SQL语法进行了扩展,可以包括代码块、循环和条件语句。
2.存储程序都被保存在服务器端,定义它们所需要的代码只需在它们被创建时通过网络传递一次,而不是每次执行都要传递一次。这大大减少了开销。
3.它们可以把复杂的计算封装为程序单元,而你可以简单地通过程序单元的名字来调用它们。你甚至可以把一组存储程序打包为一个“函数库”供其他应用程序调用。
4.它们提供了一种错误处理机制。
5.它们可以提高数据库的安全性。你可以通过选择存储程序执行时所需的权限下来对敏感数据的访问情况进行限制和调控。

存储程序。泛指各种类型的存储对象(存储函数、存储过程、触发器、事件)。存储例程(stored routine ),特指存储函数和存储过程。这两种对象的定义语法很相似,所以很自然地把它们放在一起讨论。在开始讨论各种类型的存储程序之前,我们首先学习一下:复合语句。

1.复合语句和语句分隔符

简单的存储程序只包含一条SQL语句,在编写时不需要特殊对待。下面的存储过程使用了一条SELECT语句来列出sampdb数据库里的数据表的名字:

PROCEDURE sampdb_tables()
SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_SCHEMA=’sampdb’ ORDER BY TABLE_NAME;

不过,存储程序并非只能包含一条简单的SQL语句。它们可以包含多条SQL语句,可以使用局部变量、条件语句、循环和嵌套语句块等多种语法构造。要使用这些构造编写存储程序,就需要用到复合语句。复合语句由BEGIN开头,END结束,在它们之间可以写出任意数量的语句,这些语句构成了一个语句块。下面的存储过程将显示一条欢迎消息,其中有你的用户名;如果你是一位匿名用户,用户名将是“earthing":

CREATE PROCEDURE greetings()
BEGIN#77=16  for username+60 for hostname+1 for '@'DECLARE user CHAR(77) CHARACTER SET utf8;SET user = (SELECT CURRENT USER());IF INSTR(user,’@’)>0 THEN#返回字符串在某一个字段的内容中的位置, 没有找到字符串返回0,否则返回位置(从1开始)SET user=SUBSTRING_INDEX(user, '@', 1);END IF;IF user = '' THENSET user='earthling';END IF;SELECT CONCAT('Greetings,',user, '!') AS greeting;
END;

在使用复合语句时,必须考虑和解决这样一个问题:复合语句块里的语句必须以分号(;)彼此隔开,但因为分号同时也是mysql程序默认使用的语句分隔符,所以在使用mysql程序定义存储程序时会发生冲突。
解决这个问题的办法是使用delimiter命令把mysql程序的语句分隔符重定义为另一个字符或字符串,它必须是在存储例程的定义里没有出现过的。这样一来,mysql程序就不会把分号解释为语句终止符了,它将把整个对象定义作为一条语句传递给服务器。在定义完存储程序之后,可以把mysql程序的语句终止符重新定义为分号。

use weibo;
delimiter $
CREATE PROCEDURE show_times()
BEGINSELECT 'Local time is:', CURRENT_TIMESTAMP;SELECT 'UTC time is:', UTC_TIMESTAMP;
END$
delimiter ;-- delimiter后空格加分号,将分号设置为分隔符
CALL show_times();

定义一个存储过程时把mysql程序的默认分隔符临时改变为$,然后在恢复了mysql程序的默认分隔符之后执行了那个存储过程:

 

分隔符不必非得是$字符,也不必非得是单个的字符:

delimiter EOF

这里的原则是:只要在某个存储程序内部的语句里会用到分号,就应该在定义这个存储程序时临时改变mysql程序的分隔符。

2.存储函数和存储过程

存储函数将向调用者返回一个计算结果,这个结果可以用在表达式里(就像COS()或HEX()这样的内建函数那样)。存储过程需要使用CALL语句来调用,是一个独立的操作,不能用在表达式里。使用存储过程的情况主要有两种:(1)只需通过运算来实现某种效果或动作而无需返回一个值,(2)运算会返回多个结果集(函数做不到这一点)。这只是些指导性建议,不是硬性规定。
比如说,如果你需要返回两个或更多的值,就不能使用函数。但你可以使用一个过程,因为过程支持的参数类型允许它们的值在过程执行期间被设置,而调用者可以在过程返回后去访问那些值。

存储函数要用CREATE FUNCTION语句来创建,存储过程要用CREATE PROCEDURE语句来创建。下面的例子将创建一个函数,该函数有一个代表着年份的整数参数。(为了与数据表或数据列的名字有所区别,参数命名时将使用p_前缀)。

delimiter $
CREATE FUNCTION count_born_in_year(p_year INT)
RETURNS INT
READS SQL DATA
BEGINRETURN (SELECT COUNT(*) FROM president WHERE YEAR(birtb) = p_year);
END$
delimiter ;

这个函数有一条用来表明其返回值数据类型的RETURNS子句和一个用来计算那个值的函数体。函数体至少需要包含一条RETURN语句,用来向调用者返回一个值。把计算定义为函数的好处是可以方便地执行它而无须每次都写出所有的逻辑,你可以像使用内建函数那样来调用存储函数:

SELECT count_born_in_year(1990);

你无法让一个给定的函数返回多个值。你可以编写任意多个函数,然后在同一条语句里调用它们全体。另一个办法是使用一个存储过程并通过它的OUT参数“返回”多个值。存储过程负责计算那些值并把它们赋值给相应的参数,而那些参数可以在过程返回后由调用者访问。如果你定义了一个与某个MySQL内建函数同名的存储函数,在调用它时就必须用数据库的名字对该函数的名字进行限定以避免歧义。

存储过程和存储函数很相似,但它不返回值。因此,它没有RETURNS子句或任何RETURN语句。下面这个简单的存储过程和count_born_in_year()函数很相似,它将显示一个结果集而不是把计算结果作为其返回值。

delimiter $
CREATE PROCEDURE show_born_in_year(p_year INT)
BEGINSELECT first_name, last_name, birth, deathFROM presidentWHERE YEAR(birth)=P_year;
END$
delimiter ;

与存储函数不同,存储过程不能用在表达式里,它们只能通过CALL语句来调用。如下所示:

CALL show_born_in_year(1990);

前面的例子都是选取信息,但存储例程还可以用来修改数据表,如下例所示:

delimiter $
CREATE PROCEDURE update_expiration (p_id INT UNSIGNED, p_date DATE)
BEGINUPDATE member SET expiration=p_date WHERE member_id=p_id;
END$
delimiter ;

存储函数必须遵守这样一条限制:不允许对调用本函数的语句正在读或写的数据表进行修改。存储过程通常没有这个限制,但如果它们是从存储函数里被调用,就需要遵守这条限制。

3.存储函数和存储过程的权限

存储函数和存储过程属于数据库。要想创建存储函数或存储过程,必须拥有那个数据库的CREATE ROUTINE权限。在默认的情况下,当你创建一个存储例程时,服务器将自动地把EXECUTE和ALTER ROUTINE权限授予你(如果你还没有获得这些权限),这样你才可以执行那个例程或删除它。当你删除那个例程时,服务器将自动撤销那些权限。如果你不想使用这种自动化的权限授予/撤销机制,把automatic_sp_privileges系统变量设置为0即可。

如果服务器启用了二进制日志功能,存储函数还需要遵守一些额外的限制条件(不允许创建不确定或是会修改数据的存储函数)以保证二进制日志能够安全地完成备份和复制操作。这些限制条件如下:
1.如果log_bin_trust_function_creators系统变量没有被激活,你就必须具备SUPER权限才能创建存储函数。在此前提下,你创建的每一个函数都必须是确定的,并且不得修改数据。为了表明这一点,需要使用DETERMINISTIC、NO SQL或READS SQL DATA之一来定义存储函数。
2.如果log bin_trust_function_creators系统变量已被激活,则没有任何限制。只有当你可以相信MySQL服务器上的所有用户都不会去定义不安全的存储函数时,这种设置才是最适当的。

与log_bin_trust_function_creators系统变量有关的限制条件同样适用于触发器的创建工作。

4.存储过程的参数类型

存储过程的参数分为3种类型。对于IN参数,调用者把一个值传递给过程,过程可以对这个值进行修改,但任何修改在过程返回后对调用者是不可见的。OUT参数刚好相反,过程把一个值赋值给OUT参数,这个值在过程返回后可以由调用者访问。INOUT参数允许调用者向过程传递一个值,然后再取回一个值。
要想明确地为参数指定类型,在参数表里把IN, OUT或INOUT写在参数名字前面即可。如果没有为参数指定类型,其默认类型将是IN。

在使用OUT或INOUT参数时,在调用过程时需要给出一个变量名。过程可以设置参数的值,相应的变量将在过程返回时获得那个值。如果想让某个存储过程返回多个结果值,OUT和INOUT参数类型将非常有用(存储函数只能返回一个值,不能胜任)。下面的过程演示了OUT参数的用法。它将分别统计出student数据表里的男生和女生人数并通过它的参数返回这两个计数值,让调用者可以访问它们:

delimiter $
CREATE PROCEDURE count_students_by_sex(OUT p_male INT, OUT p_female INT)
BEGINSELECT COUNT(*) FROM student WHERE sex= 'F' INTO p_female;SELECT COUNT(*) FROM student WHERE sex= 'F' INTO p_female;
END$
delimiter ;

在调用这个过程时,请把各个参数替换为相应的用户定义变量。这个过程将把计数值放到这些参数里,在它返回之后,那些变量将包含计数值:

CALL count_students_by_sex(@mcoant, @fcount);
SELECT 'Number of male students:',@mcount;

IN、OUT和INOUT关键字不适用于存储函数、触发器或事件。对于存储函数,所有的参数都像IN参数。触发器和事件则根本没有任何参数。下一部分介绍:触发器和事件。

转载于:https://www.cnblogs.com/houkai/p/3523563.html

存储程序(1)——MYSQL相关推荐

  1. mysql 以 db 结尾_MySQL的高级部分

    1. MySQL的事务 (1)存储引擎的介绍 介绍:当客户端发送一条SQL语句给服务器时,服务器端通过缓存.语法检查.校验通过之后,然后会通过调用底层的一些软件组织,去从数据库中查询数据,然后将查询到 ...

  2. 数据库学习记录806

    1. (1)基本概念 ① 属性和域: 每个事物有很多属性,每个属性对应的取值范围叫做域,所有对域都是原子数据(第一范式) ② 相关名词 n元关系:R(D1,D2,D3...Dn)是n元关系,其中关系属 ...

  3. MySQL入门系列:存储程序(二)之存储函数简介

    存储例程 存储例程是存储程序的一种类型,本质上也是封装了一些可执行的语句,只不过它的调用方式是:需要手动去调用!存储例程又可以分为存储函数和存储过程,下边我们详细唠叨这两个家伙. 存储函数 创建存储函 ...

  4. mysql连接多个存储存储_Mysql(三):多表查询和存储程序

    今天内容: ● 多表查询(内连接 外连接 子查询) ● 存储程序(存储过程 函数) 多表查询 ​同时从多张数据表中查取到需要的数据即是多表查询. 多表查询时,参与查询的表中每条数据进行组合,这种效果称 ...

  5. MySQL可不可以直接定义程序_mysql8 参考手册-定义存储程序

    每个存储的程序都包含一个由SQL语句组成的主体.该语句可以是由多个用分号(;)字符分隔的语句组成的复合语句.例如,以下存储过程的主体由一个BEGIN ... END包含一个SET 语句的块 和一个RE ...

  6. 【MySQL数据库设计与应用(六)】存储程序(存储过程,存储函数,触发器,事件)

    文章目录 1 存储程序介绍 1.1 什么是存储程序 1.2 存储例程 1.3 触发器 1.4 事件 2 创建和调用存储过程 2.1 创建和调用存储过程 2.2 存储过程的参数模式 2.3 存储过程返回 ...

  7. mysql information schema_[MySql技术]MySQL中information_schema是什么

    大家在安装或使用MYSQL时,会发现除了自己安装的数据库以外,还有一个information_schema数据库. information_schema数据库是做什么用的呢,使用WordPress博客 ...

  8. MySQL 错误代码和消息

    本章列出了当你用任何主机语言调用MySQL时可能出现的错误.首先列出了服务器错误消息.其次列出了客户端程序消息. B.1. 服务器错误代码和消息 服务器错误信息来自下述源文件: ·         错 ...

  9. Mysql使用大全 从基础到存储过程

    平常习惯了phpmyadmin等其他工具的的朋友有的根本就不会命令,如果让你笔试去面试我看你怎么办,所以,学习一下还是非常有用的,也可以知道你通过GUI工具的时候工具到底做了什么.Mysql用处很广, ...

最新文章

  1. 蓝桥杯-送分啦(java)
  2. LeetCode 382. 链表随机节点(概率)
  3. 洛谷——P1980 [NOIP2013 普及组] 计数问题
  4. Oracle 学习笔记(四) Oracle表空间和数据文件
  5. js setInterval() 用法示例
  6. codeforces 690D2 D2. The Wall (medium)(组合数学)
  7. 'System.Data.SqlClient' could not be loaded解决办法
  8. 四十三 Python分布式爬虫打造搜索引擎Scrapy精讲—elasticsearch(搜索引擎)的mapping映射管理...
  9. php 字体设计,时尚前沿:15个创意的3D字体设计艺术作品欣赏
  10. 行业大数据产品发展趋势
  11. SQL Server行列转换
  12. ABAQUS的第一个error【删去Job-1.lck】
  13. 计算机cpu有什么作用是什么意思,电脑中的cpu有什么作用?CPU是什么?
  14. DB数据库密码怎么破啊~~~求高手帮忙解决下~
  15. Microsoft Live Account for Mail, space, onecare
  16. 【CSDN AI周刊】第16期 | 黄仁勋怒怼TPU 龙之队惜败冷扑大师
  17. 印度公开病患接触者追踪应用源代码
  18. Chrome浏览器保存微信公众号文章中的图片
  19. 对象和String之间转换(包含基本类型转换)
  20. Uncaught (in promise) Error: Request failed with status code 415

热门文章

  1. 380万赌石(翡翠原石)切出2亿,现在值多少钱了?
  2. 第一次申请信用卡额度太低,怎么办?
  3. 看奥运之五:关于“鸟巢”、“水立方”的数据和内涵
  4. 单片机编程主函数的特点
  5. ads s参数拟合_ADS S参数仿真介绍
  6. java 工厂模式的写法_设计模式-工厂模式
  7. python如何关闭窗口仍能运行_Python在退出时关闭自己的CMD shell窗口
  8. fpga供电电压偏低会怎样_[走近FPGA]之开发板介绍篇
  9. Unity C# Job System介绍(二) 安全性系统和NativeContainer
  10. 3D游戏的照明设计理论,第4部分:如何在游戏引擎中照亮游戏世界