Calling a procedure inside a function throws MySQL ERROR 1422

风格不统一 提交于 2019-12-25 16:44:10

问题


I am building a "bank" as an assignment for a database course I am taking. I have created a stored function which takes a few IN variables, such as account ID, customer ID and a PIN number, and does checks on this to see if the submitted data is valid. If the data is valid, the procedure updates the account balance to represent a monetary transaction. It then "returns" whether or not the submitted data was valid. Here is the code for the procedure:

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 ;

I wanted to make it easier to view the output of the procedure, and as I'm not allowed to use transactions within a function I chose to write a wrapper function, as follows:

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 ;

Unfortunately this does not work, and I still get this following error:

ERROR 1422 (HY000): Explicit or implicit commit is not allowed in stored function or trigger.

Is this because I call the procedure, which contains transactions, inside the function?


回答1:


There are a number of statements that cause an implicit commit, and none of these can be used inside a stored function or a trigger, or in a stored procedure that is called from a stored function or trigger, because that is not really any different in its net effect.

A moment's reflection explains the reason for this: stored functions (and triggers) execute while a query is running. They always, without exception, begin executing after the query starts, and finish executing before the query finishes. They can also run multiple times during the execution of a single query, particularly when the query involves multiple rows.

In that light, it would not make sense if it were possible to COMMIT a transaction while a single query is running... and that's what START TRANSACTION does, if a transaction is running -- it implicitly commits the current transaction, and starts a new one.

This is fine in a stored procedure, as long as you're not calling it in the middle of another query (via a stored function or trigger, which is the only way to invoke a procedure in the middle of another query) but doing what you are doing here is not supported... even if there's not a transaction running, it still isn't possible to start a transaction in the middle of a running query.

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



来源:https://stackoverflow.com/questions/26096621/calling-a-procedure-inside-a-function-throws-mysql-error-1422

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!