恰好会发生的。因为对主键插入两个同样的值会导致SQLSTATE 23000错误发生,这里SQLSTATE 23000是约束错误。
2. DECLARE CONDITION声明条件
CREATE PROCEDURE p24 () BEGIN DECLARE `Constraint Violation` CONDITION FOR SQLSTATE ''23000''; DECLARE EXIT HANDLER FOR `Constraint Violation` ROLLBACK; START TRANSACTION; INSERT INTO t2 VALUES (1); INSERT INTO t2 VALUES (1); COMMIT; END; //
这个约束错误会导致ROLLBACK(回滚事务)和SQLSTATE 23000错误发生。
3. DECLARE CONDITION
mysql> CALL p24()// Query OK, 0 rows affected (0.28 sec)
mysql> SELECT * FROM t2// Empty set (0.00 sec)
我们调用这个存储过程看结果是什么,从上面结果我们看到表t2没有插入任何记录。全部事务都回滚了。这正是我们想要的。
4. DECLARE CONDITION
mysql> CREATE PROCEDURE p9 () -> BEGIN -> DECLARE EXIT HANDLER FOR NOT FOUND BEGIN END; -> DECLARE EXIT HANDLER FOR SQLEXCEPTION BEGIN END; -> DECLARE EXIT HANDLER FOR SQLWARNING BEGIN END; -> END;// Query OK, 0 rows affected (0.00 sec)
这里是三个预声明的条件:NOT FOUND (找不到行), SQLEXCEPTION (错误),SQLWARNING (警告或注释)。因为它们是预声明的,因此不需要声明条件就可以使用。不过如果你去做这样的声明:"DECLARE SQLEXCEPTION CONDITION ...",你将会得到错误信息提示。
Cursors 游标
游标实现功能摘要:
DECLARE cursor-name CURSOR FOR SELECT ...; OPEN cursor-name; FETCH cursor-name INTO variable [, variable]; CLOSE cursor-name;
现在我们开始着眼游标了。虽然我们的存储过程中的游标语法还并没有完整的实现,但是已经可以完成基本的事务如声明游标,打开游标,从游标里读取,关闭游标。
1. Cursor Example
CREATE PROCEDURE p25 (OUT return_val INT) BEGIN DECLARE a,b INT; DECLARE cur_1 CURSOR FOR SELECT s1 FROM t; DECLARE CONTINUE HANDLER FOR NOT FOUND SET b = 1; OPEN cur_1; REPEAT FETCH cur_1 INTO a; UNTIL b = 1 END REPEAT; CLOSE cur_1; SET return_val = a; END;//
我们看一下包含游标的存储过程的新例子。
2. Cursor Example
CREATE PROCEDURE p25 (OUT return_val INT) BEGIN DECLARE a,b INT; <-- DECLARE cur_1 CURSOR FOR SELECT s1 FROM t; DECLARE CONTINUE HANDLER FOR NOT FOUND SET b = 1; OPEN cur_1; REPEAT FETCH cu
|