一尘不染

在函数内部调用过程会引发MySQL错误1422

sql

我正在建立一个“银行”作为我正在上的数据库课程的作业。我创建了一个存储函数,该函数带有一些IN变量,例如帐户ID,客户ID和PIN码,并对此进行检查以查看所提交的数据是否有效。如果数据有效,则该过程将更新帐户余额以表示货币交易。然后,它“返回”提交的数据是否有效。这是该过程的代码:

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.

这是因为我在函数内部调用了包含事务的过程?


阅读 384

收藏
2021-03-17

共1个答案

一尘不染

有许多语句会导致隐式提交,并且这些语句都不能在存储函数或触发器内部使用, 也不能在从存储函数或触发器调用的存储过程中使用,
因为在这方面并没有什么不同。其净效果。

片刻的反思解释了其原因:存储的函数(和触发器) 在查询运行时执行
。它们始终无一例外地在查询开始之后开始执行,并在查询结束之前完成执行。它们在执行单个查询期间也可以运行多次,尤其是当查询涉及多行时。

有鉴于此,如果COMMIT在运行单个查询时是否有可能进行事务处理就没有任何意义了……START TRANSACTION如果事务正在运行,那就可以了-
它隐式提交了当前事务,并开始了一个新的事务。

只要您不在另一个查询的中间调用它(通过存储函数或触发器,这是在另一个查询的中间调用过程的唯一方法),这在存储过程中就可以了,不支持您在此处执行的操作…即使没有事务在运行,也仍然无法在正在运行的查询中间启动事务。

http://dev.mysql.com/doc/refman/5.6/zh-CN/implicit-
commit.html

2021-03-17