You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

含IF语句的MySQL事务出现SQL语法错误,如何解决?

修复MySQL转账事务中的语法错误(Error 1064)

错误原因

你碰到的Error Code: 1064是因为**IF、ROW_COUNT()这类流程控制逻辑属于MySQL存储程序(存储过程/函数)专属语法**,不能直接在普通交互式SQL会话里执行BEGIN...END代码块。MySQL默认客户端只支持执行基础SQL语句,不识别存储程序特有的流程控制语法。


方案1:封装为存储过程(推荐用于生产环境)

把转账逻辑写成存储过程,就能正常使用流程控制语句了:

-- 临时修改语句分隔符,避免存储过程内的分号被提前解析
DELIMITER //

CREATE PROCEDURE TransferirMonto(IN cuenta_origen INT, IN cuenta_destino INT, IN monto_transferir DECIMAL(10,2))
BEGIN
    -- 加行锁防止并发修改
    SELECT saldo FROM cuentas WHERE id_cuenta = cuenta_origen FOR UPDATE;
    SELECT saldo FROM cuentas WHERE id_cuenta = cuenta_destino FOR UPDATE;

    -- 尝试扣除源账户余额(仅当余额足够时执行)
    UPDATE cuentas
    SET saldo = saldo - monto_transferir
    WHERE id_cuenta = cuenta_origen AND saldo >= monto_transferir;

    -- 判断扣除操作是否成功
    IF ROW_COUNT() = 0 THEN
        ROLLBACK;
        SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'Saldo insuficiente en la cuenta de origen';
    ELSE
        -- 增加目标账户余额
        UPDATE cuentas
        SET saldo = saldo + monto_transferir
        WHERE id_cuenta = cuenta_destino;
        COMMIT;
    END IF;
END //

-- 恢复默认分隔符
DELIMITER ;

调用存储过程执行转账:

CALL TransferirMonto(1, 2, 100.00);

方案2:无存储过程的临时执行写法

如果只是临时测试,不想创建存储过程,可以调整为如下写法(利用会话变量替代流程控制):

START TRANSACTION;

-- 查询并锁定源账户余额
SET @saldo_disponible = (SELECT saldo FROM cuentas WHERE id_cuenta = 1 FOR UPDATE);

IF @saldo_disponible >= 100.00 THEN
    UPDATE cuentas SET saldo = saldo - 100.00 WHERE id_cuenta = 1;
    UPDATE cuentas SET saldo = saldo + 100.00 WHERE id_cuenta = 2;
    COMMIT;
    SELECT 'Transferencia exitosa' AS resultado;
ELSE
    ROLLBACK;
    SELECT 'Saldo insuficiente en la cuenta de origen' AS error;
END IF;

额外注意事项

  • FOR UPDATE行锁的使用是正确的,能避免并发转账时的脏数据问题,保证事务的一致性。
  • SIGNAL语句仅支持在存储程序中使用,所以临时写法里用SELECT返回错误信息替代。

内容的提问来源于stack exchange,提问作者pamela giron

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 04:42:17