储存过程是最常见的储存程序,储存过程是能够接受数个输入和输出参数并且能够在请求时被执行的程序单元。储存函数
储存函数和储存过程很相像,但是它的执行结果会返回一个值。最重要的是储存函数可以被用来充当标准的SQL表达式,允许程序员有效的扩展SQL语言的能力。触发器
触发器是用来响应激活或者数据库行为,事件的储存程序,通常,触发器用来作为DML(数据库操纵语言)的响应而被调用,触发器可以被用来作为数据校验和自动反向格式化。在这本书中,我们将使用术语:储存程序来带指储存过程,函数和触发器,术语:储存程序语言带指用来写这些程序的语言,大多数程序的基本构建都可以在储存过程,函数和触发器中被使用;但是,储存函数和触发器在使用这些构建时是严格受限的。所以我们将另辟章节来专门介绍这些程序类型的限制。
其他的数据库提供了别的储存程序,包括包和类 — 允许你定义和组织一堆上下文过程和函数,MySQL现在还不提供这种结构,每个程序都是一个单独的实体。
行号 | 解释 |
1 | 这个区块,是程序的头部,定义了程序的名称(example1)以及类型(PROCEDURE) |
2 | BEGIN关键字指示了程序体的开始,其中包含了储存过程的变量申明和可执行代码,如果程序体包含了超过一个表达式(就像这个程序中所看到的一样),那么要将多个表达式包含在BEGIN-END块中 |
3 | 这里我们申明了一个整型的变量来保存我们将要执行的数据库查询代码 |
5-8 | 我们执行了一个数据库查询来获得Guy所编写和执笔的属的总数,特别关注一些第6行:INTO子句和SELECT连用表示将数据库查询结果传递给储存程序的本地变量 |
10-12 | 我们是用了一个简单的SQL表达式(例如:没有带FROM字句)来显示书的个数。如果我们使用了没有带INTO字句的SELECT语句,那么结果将返回给调用程序,这是一个能够简单的得到结果集的非ANSI扩展(SQL Server和其他关系型数据库所采用的方式) |
14 | 单行注释解释了UPDATE的用意 |
15-17 | Guy大概想和他的fans讨论有关Oracle,并想改变他姓的拼写方法,所以我们对books表使用了UPDATE,得益于内建的REPLACE函数我们能将表中所有包含“GUY”的实例替换为“GUILLERMO”。 |
行号 | 解释 |
1-3 | 这是储存过程的头部;第二行包含了过程的参数列表,接受一个数据参数(帐户的id) |
6 | 申明了一个保存帐余额的变量 |
8-18 | 一个简单循环(这样称呼是因为使用LOOP关键字来和WHILE及REPEAT进行区别)直到帐户余额少于1000,在MySQL中我们可以命名一个循环(第8行,payout_loop),这使得我们可以在随后的代码中使用LEAVE表达式(见第12行)来结束这个特定的循环,结束循环后,MySQL引擎将执行END LOOP(见第18行)之后的代码 |
9 | 调用了函数account_balance(当然这个函数必须已经在前面的代码中被定义)来获得帐户的收支状况。MySQL允许我们在储存程序中调用别的储存程序,这可以有效的实现代码复用,如果这是一个函数,那么它将返回一个值并且能被其他储存程序和MySQL作业调度所调用 |
11-16 | IF表达式引发了当帐户余额少于1000美元时的循环终结条件,此外(ELSE表达式)能够对收支平衡进行进一步处理,你可以用ELSEIF构建更为负责的布尔表达式 |
15 | 调用了储存过程apply_balance,这是一个代码复用的例子,与其重复apply_balance的逻辑,我们还是调用一个共享例程比较方便 |
行号 | 解释 |
1 | 定义函数:名称,参数(日期)和返回值(整型数)。 |
2 | 这个函数没有使用SQL表达式,这将在第3章和第10章进行详细的讨论 |
4 | 申明一个用来保存我们计算出的年龄的本地变量 |
5-11 | 在这个IF-ELSE-END块中,IF块用来检测出生年月是否存在 |
7 | 如果出生年月存在,那么我们就可以用现在的年份减去出生的年份得到年龄 |
10 | 此外(如果出生年月不存在),我们必须在岁数计算中简单的减去当前的年份 |
12 | 返回年份计算的函数调用 |
行号 | 解释 |
1-4 | 这是程序的头部,包含了两个输入参数产品代号和产品名称 |
7 | 申明了一个用来检测重复值出现的标志变量,这个变量被初始化为0(false);后续的代码将保证在重复值被替换时将把这个变量设置为1(true)。 |
8 | 命名一个条件duplicate_key和MySQL系统错误1062相匹配,虽然这一步并非必需,但是我们建议你定义一个条件来改善你代码的可靠性(现在你可以使用错误名称而不是代码来引用这个错误) |
9 | 定义一个错误处理器,它将在后续的代码中重复值出现的时候将l_dupkey_indicator变量的值设置为1(true) |
11-12 | 插入用户提供的代号和名称 |
14 | 检测变量l_dupkey_indicator的值,如果仍为0,那么说明我们的插入成功了,如果值被修改成了1(true),我们就知道出现了重复值,我们可以在地15-17行代码使用UPDATE表达式将原来的产品名称和代号进行更新 |
行号 | 解释 |
1 | 一个触发器有它独立的名称,通常,我们用名称来描述它的作用,举例来说,名称中的“bu”表示BEFORE UPDATE(在更新前)使用的触发器 |
2 | 定义一个触发器激活条件,在这个例子中,触发器代码将在UPDATE表达式起作用前被触发 |
3 | FOR EACH ROW关键字指示了触发器将在所有的记录被DML表达式作用前被触发。这个字句在MySQL5的触发器实现中是强制执行的 |
4-10 | BEGIN-END定义了将被激活的触发器代码 |
5-9 | 自动修改emplyees表中contrib_401K列。如果salary列的值小于50000,contrib_401K列将被设置为500,否则,这个值就参与执行第8行的计算 |
如果你在30分钟内不能指出代码中的bug,那么请立即请教别人,这样也就建立了一种“责任机制”,使得每一个被你问起的人都有一种责任感。不要让你一个人孤立的寻找问题的答案。建立一种代码互查机制
不要让你的代码敲上“金牌质量”的标签或者经不起你团队中任何人的批评(建设性的意见)
欢迎光临 MariaDB社区 (http://123.56.88.72/) | Powered by Discuz! X3.2 |