MySQL 的存储过程写法和Cursor的使用

以下文章转自:

http://www.blogjava.net/itstarting/archive/2006/10/10/74256.html

MySQL 的存储过程写法和Cursor的使用

对于MySQL,还是菜鸟。
近期做个东西,写了一个MySQL 的存储过程,其中涉及Cursor的使用,如下:

CREATE PROCEDURE `justifyGroupNum`()
    NOT DETERMINISTIC
    SQL SECURITY DEFINER
    COMMENT ''
BEGIN
/*how to run:call justifyGroupNum()*/
DECLARE p_group_id int;
declare p_num int;
declare stopFlag int;
DECLARE cursor_name CURSOR
  FOR select c_group_id,count(*) as num
      from `t_group_member`
      where c_valid in (3,4)
      group by c_group_id;
DECLARE CONTINUE HANDLER FOR NOT FOUND set stopFlag=1;

OPEN cursor_name;
REPEAT
FETCH cursor_name INTO p_group_id,p_num;
  begin
       update t_groupinfo set c_member_number=p_num where c_group_id=p_group_id;
  end;
UNTIL stopFlag = 1
END REPEAT;
CLOSE cursor_name;
END;

关注点有:
1、注意设置游标的countinue handler:DECLARE CONTINUE HANDLER FOR NOT FOUND set stopFlag=1;
2、注意REPEAT和UTILE [停止条件] END REPEAT的使用,否则不会循环;
3、怎样RUN?输入并执行:call justifyGroupNum() 

<think>嗯,用户想了解MySQLOracle存储过程的区别,特别是主要差异语法特点。我需要先回顾一下相关的知识点,确保回答准确。 首先,存储过程在两种数据库中的作用相似,都是预先编译的SQL代码块,但语法功能上确实有不同。记得之前看过引用1引用2提到它们的语法差异较大,比如变量声明、流程控制结构可能不一样。比如Oracle使用PL/SQL,而MySQL可能有自己的语法。 然后,变量声明部分,Oracle通常用DECLARE,而MySQL使用DECLARE但需要放在BEGIN之后,或者在参数中使用@符号。这点需要对比举例说明。 参数传递方面,Oracle有IN、OUT、IN OUT三种模式,而MySQL的参数模式需要明确指定IN、OUT、INOUT,而且参数名前不用加@。比如在创建存储过程时,参数定义的写法不同。 事务处理部分,Oracle每个DDL语句都会自动提交,而MySQL默认自动提交,所以在存储过程中可能需要用START TRANSACTION来手动控制。这点引用3提到Oracle使用行级锁,可能事务处理有关联,但需要更直接比较两者的事务处理机制。 错误处理机制,Oracle有完善的EXCEPTION块,可以定义多种异常处理,而MySQL使用DECLARE HANDLER,功能相对简单。比如Oracle的WHEN OTHERS THEN处理未捕获异常,而MySQL需要用条件处理。 游标的使用也可能不同,比如Oracle的游标处理更灵活,支持参数化游标,而MySQL的游标只能在存储过程使用,且声明方式不同。需要分别举例子说明两者的游标语法。 另外,返回结果集的方式,Oracle可能需要使用游标或OUT REF CURSOR,而MySQL可以直接SELECT返回结果集。比如Oracle的存储过程返回结果集可能需要定义SYS_REFCURSOR,而MySQL存储过程在调用时可以直接获取结果。 还有,存储过程的调试工具支持可能不同,Oracle有更成熟的开发工具,比如PL/SQL Developer,而MySQL可能需要使用第三方工具或命令行调试。这点用户可能也会关心,但引用中没有提到,可能需要根据知识补充。 最后,总结两者的适用场景,比如Oracle适合复杂企业应用,MySQL适合轻量级应用。同时,引用3提到Oracle使用行级锁,可能在并发处理上有优势,而MySQL的锁机制可能不同,这也可能影响存储过程的设计。 需要确保回答结构清晰,分点列出差异,并给出示例代码对比,帮助用户理解。同时检查引用是否正确应用,比如引用1、2、3、4中的相关内容是否恰当引用,比如事务处理部分引用3,语法差异引用12等。</think>### MySQL与Oracle存储过程的主要差异及语法特点 #### 一、基础语法差异 1. **存储过程声明** - **Oracle** 使用 `CREATE OR REPLACE PROCEDURE` 语法,支持覆盖已有存储过程: ```sql CREATE OR REPLACE PROCEDURE proc_name (参数列表) IS BEGIN -- 逻辑代码 END; ``` - **MySQL** 使用 `CREATE PROCEDURE`,若需覆盖需先删除原过程: ```sql DROP PROCEDURE IF EXISTS proc_name; CREATE PROCEDURE proc_name (参数列表) BEGIN -- 逻辑代码 END; ``` 2. **参数模式** - **Oracle** 支持 `IN`(输入)、`OUT`(输出)、`IN OUT`(输入输出)三种模式,例如: ```sql CREATE PROCEDURE oracle_proc (p1 IN NUMBER, p2 OUT VARCHAR2) IS ... ``` - **MySQL** 参数模式需显式声明为 `IN`、`OUT` 或 `INOUT`,且参数名前无需符号修饰: ```sql CREATE PROCEDURE mysql_proc (IN p1 INT, OUT p2 VARCHAR(20)) BEGIN ... END; ``` #### 二、变量与赋值 1. **变量声明** - **Oracle** 在 `DECLARE` 块中声明(位于 `BEGIN` 前): ```sql DECLARE v_num NUMBER := 10; BEGIN -- 使用变量 END; ``` - **MySQL** 变量需在 `BEGIN` 后声明,局部变量用 `DECLARE`,会话变量用 `@`: ```sql BEGIN DECLARE v_num INT DEFAULT 10; SET @session_var = 20; END; ``` 2. **赋值操作** - **Oracle** 使用 `:=` 或 `SELECT INTO`: ```sql v_num := 100; SELECT COUNT(*) INTO v_num FROM table; ``` - **MySQL** 使用 `SET` 或 `SELECT INTO`,但需注意作用域: ```sql SET v_num = 100; SELECT COUNT(*) INTO v_num FROM table; ``` #### 三、流程控制对比 1. **条件语句** - **Oracle** 使用 `IF-THEN-ELSIF-ELSE` 结构: ```sql IF condition THEN -- 逻辑 ELSIF condition2 THEN -- 逻辑 ELSE -- 逻辑 END IF; ``` - **MySQL** 语法类似,但关键字为 `ELSEIF`: ```sql IF condition THEN -- 逻辑 ELSEIF condition2 THEN -- 逻辑 ELSE -- 逻辑 END IF; ``` 2. **循环结构** - **Oracle** 支持 `LOOP`、`WHILE`、`FOR`: ```sql FOR i IN 1..10 LOOP -- 循环体 END LOOP; ``` - **MySQL** 使用 `LOOP`、`REPEAT`、`WHILE`,需显式控制退出: ```sql WHILE condition DO -- 循环体 END WHILE; ``` #### 四、事务与异常处理 1. **事务控制** - **Oracle** 默认自动提交,但存储过程中可显式控制: ```sql COMMIT; -- 手动提交 ROLLBACK; -- 回滚 ``` - **MySQL** 默认自动提交,需通过 `START TRANSACTION` 开启事务: ```sql START TRANSACTION; -- DML操作 COMMIT; ``` 2. **异常处理** - **Oracle** 使用 `EXCEPTION` 块捕获错误,支持自定义异常: ```sql BEGIN -- 逻辑 EXCEPTION WHEN NO_DATA_FOUND THEN -- 处理异常 END; ``` - **MySQL** 通过 `DECLARE HANDLER` 定义错误处理: ```sql DECLARE EXIT HANDLER FOR SQLEXCEPTION BEGIN -- 处理异常 END; ``` #### 五、游标与结果集返回 1. **游标操作** - **Oracle** 支持显式游标 `REF CURSOR`(返回结果集): ```sql CURSOR cur IS SELECT * FROM table; OPEN cur; FETCH cur INTO variables; CLOSE cur; ``` - **MySQL** 游标需在存储过程中声明使用,且不支持参数化游标: ```sql DECLARE cur CURSOR FOR SELECT * FROM table; OPEN cur; FETCH cur INTO variables; CLOSE cur; ``` 2. **返回结果集** - **Oracle** 需通过 `OUT` 参数返回 `SYS_REFCURSOR`: ```sql CREATE PROCEDURE get_data (p_result OUT SYS_REFCURSOR) IS BEGIN OPEN p_result FOR SELECT * FROM table; END; ``` - **MySQL** 直接执行 `SELECT` 即可返回结果集: ```sql CREATE PROCEDURE get_data() BEGIN SELECT * FROM table; END; ``` #### 六、典型场景示例 **Oracle 存储过程(计算并返回统计值)** ```sql CREATE OR REPLACE PROCEDURE calc_stats ( p_dept_id IN NUMBER, p_avg_sal OUT NUMBER ) IS BEGIN SELECT AVG(salary) INTO p_avg_sal FROM employees WHERE department_id = p_dept_id; EXCEPTION WHEN NO_DATA_FOUND THEN p_avg_sal := 0; END; ``` **MySQL 存储过程(同类功能)** ```sql CREATE PROCEDURE calc_stats ( IN p_dept_id INT, OUT p_avg_sal DECIMAL(10,2) ) BEGIN DECLARE EXIT HANDLER FOR NOT FOUND SET p_avg_sal = 0; SELECT AVG(salary) INTO p_avg_sal FROM employees WHERE department_id = p_dept_id; END; ``` #### 七、适用场景对比 - **Oracle**:适合高并发、复杂业务逻辑的企业级应用,需严格事务控制大数据处理[^3]。 - **MySQL**:适用于轻量级应用、快速开发场景,尤其是Web应用读写分离架构。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值