MySQL基础(四)存储过程

一、存储过程的优点
    1.存储过程只在创造时进行编译,以后每次执行存储过程都不需再重新编译,而一般SQL语句每执行一次就编译一次,所以使用存储过程可提高数据库执行速度。

  2.当对数据库进行复杂操作时(如对多个表进行Update,Insert,Query,Delete),可将此复杂操作用存储过程封装起来与数据库提供的事务处理结合一起使用。

  3.存储过程可以重复使用,可减少数据库开发人员的工作量

  4.安全性高,可设定只有某此用户才具有对指定存储过程的使用权  

二、执行存储过程
    CALL producname(@parm1,@parm2);

三、创建存储过程
    create procedure proceName(OUT parm1 DECIMAL(8,2)
                              OUT parm2 DECIMAL(8,2))
    BEGIN
   
    select ....

    END;

    OUT用来指定需要从存储过程传出来的值。IN传递给存储过程。INOUT传入或传出。

四、例子
DELIMITER $$ #默认情况下,delimiter是分号;。在命令行客户端中,如果有一行命令以分号结束,那么回车后,mysql将会执行该命令。如输入下面的语句

DROP PROCEDURE IF EXISTS `rechargeproce`$$

CREATE PROCEDURE `rechargeproce`()

BEGIN
DECLARE rechargeid INT; #定义局部变量
DECLARE invoiceid INT;
DECLARE mailcharge DOUBLE;
DECLARE done INT DEFAULT 0;
DECLARE rechargecursor CURSOR #创建游标
FOR
SELECT r.rc_id,i.iv_id,i.mail_charge FROM finance_recharge r,finance_invoice i WHERE r.procedure_fee < 0 AND r.rc_order_num = i.order_num AND i.mail_charge > 0 ORDER BY r.creat_time; 
DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET done = 1; #设置循环结束的标准,这个地方是所有的结果遍历完
OPEN rechargecursor;    
REPEAT
FETCH rechargecursor INTO rechargeid,invoiceid,mailcharge;
UPDATE finance_recharge SET procedure_fee=ROUND(rc_money/0.996-rc_money,2),rc_money = rc_money-mailcharge WHERE rc_id = rechargeid;
UPDATE finance_invoice SET iv_amount = iv_amount-mailcharge WHERE iv_id =  invoiceid;
UNTIL done END REPEAT;
END$$

DELIMITER ;

SET autocommit = 0; #如果涉及到大批量数据的修改,最好先设置数据库不自动提交

CALL rechargeproce; #调用存储过程

ROLLBACK; #语句有错,回滚
COMMIT; #语句正确,提交

例子2:
DELIMITER $$

DROP PROCEDURE IF EXISTS `updatesxf`$$

CREATE PROCEDURE `updatesxf`()
BEGIN
DECLARE oldsxf DOUBLE;
DECLARE rcid INT;
DECLARE rcmoney DOUBLE;
DECLARE amont DOUBLE;
DECLARE mailcharge DOUBLE DEFAULT 0;
DECLARE newsxf DOUBLE;
DECLARE done INT DEFAULT 0;
DECLARE sxfcursor CURSOR FOR
SELECT r.rc_id,r.rc_money,r.procedure_fee,i.mail_charge FROM finance_recharge r LEFT JOIN finance_invoice i ON r.rc_order_num = i.order_num
WHERE r.creat_time >= '2012-08-20' AND r.creat_time < '2012-08-21 18:09';
DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET done = 1;
OPEN sxfcursor;
REPEAT
FETCH sxfcursor INTO rcid,rcmoney,oldsxf,mailcharge;
IF mailcharge IS NOT NULL  THEN
SET amont= ROUND(rcmoney+mailcharge+oldsxf,2);
ELSE
SET amont= ROUND(rcmoney+oldsxf,2);
END IF;
IF amont > 25 THEN
SET amont= ROUND(amont-amont*0.004,2);
SET newsxf = ROUND(amont/0.996 - amont,2);
ELSE
SET amont= ROUND(amont-0.1,2);
SET newsxf = 0.1;
END IF;
IF amont > 16 THEN
UPDATE finance_recharge SET procedure_fee = newsxf,rc_money = amont WHERE rc_id = rcid;
END IF;
UNTIL done END REPEAT;
         CLOSE sxfcursor;

END$$

DELIMITER ;

SET autocommit = 0;
CALL updatesxf;
ROLLBACK;
COMMIT;

SELECT r.rc_id,r.rc_order_num,r.rc_money,r.procedure_fee,i.mail_charge FROM finance_recharge r LEFT JOIN finance_invoice i ON r.rc_order_num = i.order_num
WHERE r.creat_time >= '2012-08-20' AND r.creat_time < '2012-08-21 18:09';

注意:在mysql中查询和更新同一个表时,在查询的语句中不能用要更新的字段作为查询条件

猜你喜欢

转载自lsg0220.iteye.com/blog/1632098