我正在建立一个“银行”作为我正在上的数据库课程的作业。我创建了一个存储函数,该函数带有一些IN变量,例如帐户ID,客户ID和PIN码,并对此进行检查以查看所提交的数据是否有效。如果数据有效,则该过程将更新帐户余额以表示货币交易。然后,它“返回”提交的数据是否有效。这是该过程的代码:
IN
DELIMITER // CREATE PROCEDURE retrieveMoney ( IN holder INT, IN pin VARCHAR(4), IN account INT, IN amount FLOAT, OUT success INT ) BEGIN START TRANSACTION; SELECT COUNT(id) INTO success FROM account_holder WHERE id=holder AND pin=pin; IF success IS NOT NULL THEN IF (SELECT balance-amount FROM account WHERE id=account) >= 0 THEN UPDATE account SET balance = balance-amount WHERE id=account; CALL logTransaction(account,NULL,amount); COMMIT; ELSE ROLLBACK; END IF; ELSE ROLLBACK; END IF; END// DELIMITER ;
我想使查看过程输出更加容易,并且由于不允许在一个函数中使用事务,因此选择编写一个包装器函数,如下所示:
DELIMITER // CREATE FUNCTION retrieveMoney ( holder INT, pin VARCHAR(4), account INT, amount FLOAT ) RETURNS INT BEGIN CALL retrieveMoney(holder,pin,account,amount,@success); RETURN @success; END// DELIMITER ;
不幸的是,这不起作用,并且仍然出现以下错误:
ERROR 1422 (HY000): Explicit or implicit commit is not allowed in stored function or trigger.
这是因为我在函数内部调用了包含事务的过程?
有许多语句会导致隐式提交,并且这些语句都不能在存储函数或触发器内部使用, 也不能在从存储函数或触发器调用的存储过程中使用, 因为在这方面并没有什么不同。其净效果。
片刻的反思解释了其原因:存储的函数(和触发器) 在查询运行时执行 。它们始终无一例外地在查询开始之后开始执行,并在查询结束之前完成执行。它们在执行单个查询期间也可以运行多次,尤其是当查询涉及多行时。
有鉴于此,如果COMMIT在运行单个查询时是否有可能进行事务处理就没有任何意义了……START TRANSACTION如果事务正在运行,那就可以了- 它隐式提交了当前事务,并开始了一个新的事务。
COMMIT
START TRANSACTION
只要您不在另一个查询的中间调用它(通过存储函数或触发器,这是在另一个查询的中间调用过程的唯一方法),这在存储过程中就可以了,不支持您在此处执行的操作…即使没有事务在运行,也仍然无法在正在运行的查询中间启动事务。
http://dev.mysql.com/doc/refman/5.6/zh-CN/implicit- commit.html