MySQL必知必会知识预览
第一章——了解SQL
第二章——MySQL简介
第三章——使用MySQL
第四章——检索数据
第五章——排序检索数据
第六章——过滤数据
第七章——数据过滤
第八章——用通配符进行过滤
第九章——用正则表达式进行搜索
第十章——创建计算字段
第十一章——使用数据处理函数
第十二章——汇总数据
第十三章——分组数据
第十四章——使用子查询
第十五章——联结表
第十六章——创建高级联结
第十七章——组合查询
第十八章——全文本搜索
第十九章——插入数据
第二十章——更新和删除数据
第二十一章——创建和操纵表
第二十二章——使用视图
第二十三章——使用储存过程
第二十四章——使用游标
第二十五章——使用触发器
第二十六章——管理事务处理
第二十七章——全球化和本地化
第二十八章——安全管理
第二十九章——数据库维护
第三十章——改善性能
————————————– 华丽的分隔符 ————————————————–
什么是存储过程、为什么要使用存储过程、如何使用存储过程、创建和使用存储过程的基本语法
————————————– ————————————– ————————————–
理解:
大多说SQL语句都是针对一个或者多个表的单条语句。并非所有的操作都是这么简单,经常会有一个完整的操作需要多条语句才能完成。我们考虑一下情景:
1)为了处理订单,我们需要核对以保证库存中有相应的物品。
2)如果库存有物品,这些物品需要预定以便不将他们再卖给别人,并且要减少可用的物品数量以反映正确的库存量。
3)库存中没有的物品需要订购,这需要与供应商进行某种交互。
4)关于哪些物品入库(并且可以立即发货)和哪些物品退订,需要通知相应的客户。
执行这些处理需要针对许多表的多条MySQL语句。另外,需要执行的具体语句及次序也不是固定的,他们可能会(和将)根据哪些物品在库存中哪些不在而变化。
那么,我们该如何编写代码?
首先我们可以单独的编写每条语句,并根据结果又条件地执行另外的语句。在每次需要这个处理时(或者每个需要他的应用中)都必须做这些工作。
那么。有没有简单的方法?
于是,我们可以创建存储过程。
存储过程就是为了以后的使用而保存的一条或者多条MySQL语句的集合。可将视为批文件,虽然他们的作用不仅限于批处理、
1.通过把处理封装在容易使用的单元中,简化复杂的操作;
2.由于不要求反复建立一系列处理步骤,着保证了数据的完整性。如果所有开发人员和应用程序都使用同一(实验和测试)存储过程,则所使用的代码都是相同的。这一点的延伸就是防止错误。需要执行的步骤越多,出错的可能性就越大,防止错误保证了数据的一致性。
3.简化对变动的管理,如果表名。列名或者业务逻辑等有变化,只需要更改存储过程的代码。使用它的人员甚至不需要知道这些变化。这一点延伸就是安全性,通过存储过程限制对基数据的访问减少了数据讹误的机会。
4.提高性能。因为使用存储过程比使用单独的sql语句更快。
5.存在一些只能用在单个请求的MySQL元素和特性,存储过程可以使用他们来编写功能更强更灵活的代码
综上:
三个主要的好处:简单、安全、高性能。
两个缺陷:
1、存储过程的编写更为复杂,需要更高的技能更丰富的经验。
2、可能没有创建存储过程的安全访问权限。许多数据库管理员限制存储过程的 创建权限,允许使用,不允许创建。
Call关键字:Call接受存储过程的名字以及需要传递给他的任意参数。存储过程可以显示结果,也可以不显示结果。
非命令窗下创建存储过程【可视化工具】:
CREATE PROCEDURE productpricing()
BEGIN
SELECT AVG( prod_price) as priceaverage FROM products;
END;
创建名为productpricing的储存过程。如果存储过程中需要传递参数,则将他们在括号中列举出来即可。括号必须带(有没有很类似于java中的函数)。BEGIN和END关键字用来限制存储过程体。上述存储过程体本身是一个简单的select语句。注意这里只是创建存储过程并没有进行调用。
注意注意再注意:
命令行客户机的分隔符
MySQL默认的分隔符为 ;mysql命令行实用程序也是实用;作为语句分隔符。 如果命令行使用程序要解释的存储过程自身内的;字符,则他们终将不会成为储存过程的成分,这回使存储过程中的SQL语句出现语法错误。
解决办法就是临时更改命令行实用程序的语句分隔符
使用关键字delimiter
命令窗下的创建储存过程:
Delimiter // //解释使用新的符号//作为结束分隔符
Create procedure productpring()
Begin
Select AVG(prod_price) as priceaverage from products; //语句一定带符号
End // // 结束用新的分隔符
Delimiter ; //重新还原默认的分号分隔符
除了\符号外,任何字符都可以用于语句分隔符。记得在使用新的符号作为结束分隔符后,要记得还原。
存储过程是一种特殊的函数,所以存储过程名后需要有()符号,不管是否带参
储存过程的使用:
删除存储过程 关键字DROP;
注意:当我们删除不存在的存储过程时,系统会给我们报错,因此我们可以使用”if exists “ 进行过滤。仅当存在时,进行删除。还有,删除存储过程只给出储存过程名即可,不需要带括号,(一般带括号的都表示直接运行)
一般存储过程并不显示结果,而是把结果返回给你指定的变量上。
变量:内存中一个特定的位置,用来临时存储数据。
mysql> CREATE PROCEDURE prod(
out pl decimal(8,2),
out ph decimal(8,2),
out pa decimal(8,2)
)
begin
select Min(prod_price) into pl from products;
select MAx(prod_price) into ph from products;
select avg(prod_price) into pa from products;
end;
call PROCEDURE(@pricelow,@pricehigh,@priceaverage);
select @pricelow;
select @pricehigh;
select @pricelow,@pricehigh,@priceaverage;
解释:
此存储过程接受3个参数,pl存储产品最低价,ph存储产品最高价,pa存储产品平均价。每个参数必须指定类型,使用的为十进制,关键字OUT 指出相应的参数用来从存储过程传出一个值(返回给调用者)。
MySQL支持in(传递给存储过程)、out(从存储过程传出,这里所用)和inout(对存储过程传入和传出)类型的参数。存储过程的代码位于begin和end语句内。他们是一系列select语句,用来检索值。然后保存到相对应的变量(通过INTO关键字)。
存储过程的参数允许的数据类型与表中使用的类型相同。注意记录集是不被允许的类型,因此,不能通过一个参数返回多个行和列,这也是上面为什么要使用3个参数和3条select语句的原因。
调用:为调用此存储过程,必须指定3个变量名。如上所示。3个参数是存储过程保存结果的3个变量的名字。调用时,语句并不现实任何数据,他返回以后可以显示的变量(或在其他处理中使用)。
注意:所有的MySQL变量都是以@开头。
CREATE PROCEDURE ordertotal(
IN innumber int,
OUT outtotal decimal(8,2)
)
BEGIN
SELECT Sum(item_price * quantity) FROM orderitems WHERE order_num = innumber INTO outtotal;
end //
CALL ordertotal(20005,@total);
select @total; // 得到20005订单的合计
CALL ordertotal(20009,@total);
select @total; //得到20009订单的合计
解释:
In 表示传进去的参数
OUT 表示传出来的参数
Into 表示将计算结果放入到参数中
上面的存储过程基本都是封装MySQL简单的select语句。虽然他们是正确有效的存储过程例子,但是他们所完成的工作可以直接用这些封装的语句完成。(如果说他们还能到来更多的东西,那就是使事情更复杂)。只有在存储过程内包含业务柜子和只能处理时,他们的威力才真正显示出来。
思考:
你现在需要获得与以前一样的订单合计,但是,需要对合计增加营业税,不过,只是针对某些顾客(或许是你所在的城市的那些顾客)。那么,你需要做
1)获得合计(与以前一样);
2)把营业税有条件的添加到合计中;
3)返回合计(带或不带税);
-- Name:ordertotal
-- Parameters: onumber = order number
-- taxable = 0 if not taxable,1 if taxable
-- ototal = order total variable
CREATE PROCEDURE ordertotal(
IN onumber INT,
IN taxable BOOLEAN,
OUT ototal DECIMAL(8,2)
)COMMENT 'Obtain order total, optionally adding tax'
BEGIN
-- declear variable for total
DECLARE total DECIMAL(8,2);
-- declear tax percentage
DECLARE taxrate INT DEFAULT 6;
-- get the order total
SELECT Sum(item_price * quantity) FROM orderitems WHERE order_num = onumber INTO total;
-- IS this taxable?
IF taxable THEN
-- yes ,so add taxrate to the total
SELECT total+(total/100*taxrate)INTO total;
END IF;
-- finally ,save to out variable
SELECT total INTO ototal;
END;
解释:
首先,我们增加了注释(前面放置 –),这在存储过程比较复杂时,这样做特别重要。另外,添加了一个参数taxable,布尔值,表示要增加税为真,否则为假,在存储过程中我们使用了DECLARE语句,他们表示定义两个局部变量,DECLARE要求指定变量名和数据类型。它也支持可选的默认值(taxrate默认6%),因为后期我们还要判断要不要增加税,所以,我们把SELECT查询的结果存储到局部变量total中,然后在IF 和THEN的配合下,检查taxable是否为真,然后在真的情况下,我们利用另一条SELECT语句增加营业税到局部变量total中,然后我们再利用SELECT语句将total(增加税或者不增加税的结果)保存到总的ototal中。
COMMENT关键字 上面的COMMENT是可以给出或者不给出,如果给出,将在SHOW PROCEDURE STATUS的结果中显示。
SHOW CREATE PROCEDURE ordertotal; // 输出创建存储过程的语句
SHOW PROCEDURE STATUS; //获取存储过程的详细信息,包括何时,由谁创建等信息,输出的为数据库中所有的存储过程
SHOW PROCEDURE STATUS LIKE ‘ordertotal’; 关键字LIKE限制过程输出,输出指定的存储过程
———————————————— —————————————– —————————-
后期补充:
1、存储过程在利用参数时,将结果赋值给输出参数时,应该利用【SELECT … … INTO 】【set …..】语句
【select v_a into v_c;】 等价于【set v_c = v_a;】或者【set v_c := v_a;】
create procedure p(
-> in v_a int,in v_b int,out v_c int,inout v_d int)
-> begin
-> if(v_a > v_b) then
-> select v_a into v_c;
-> else
-> select v_b into v_c;
-> end if;
-> select (v_d+1) into v_d;
-> end; //
Query OK, 0 rows affected (0.08 sec)
mysql> set @v_d = 6//
Query OK, 0 rows affected (0.00 sec)
mysql> call p(2,3,@v_c,@v_d)//
Query OK, 1 row affected (0.01 sec)
mysql> select @v_c//
+------+
| @v_c |
+------+
| 3 |
+------+
1 row in set (0.00 sec)
mysql> select @v_d//
+------+
| @v_d |
+------+
| 7 |
+------+
1 row in set (0.01 sec)
解释 :set @v_d = 6 定义一个变量设置值为6,
call p(2,3,@v_c,@v_d) 执行存储过程 输入参数直接赋值,输出参数利用变量进行引用,既为输入又为输出,先利用set 变量进行赋值,然后再将此变量引入到存储过程参与运算。
select @v_c 进行结果查询