【问题标题】:How to check if previous query was executed correctly?如何检查先前的查询是否正确执行?
【发布时间】:2021-08-11 09:33:15
【问题描述】:

我必须从一个用户帐户中减少资金并增加另一个用户帐户,即将资金从一个帐户转移到另一个帐户。 例如,我在 MySql 中有此代码:

START TRANSACTION;
UPDATE accounts
SET balance = (balance-100)
WHERE account_id = 2 AND balance>100;

--If the above query is succesfully then:
UPDATE accounts
SET balance = (balance+100)
WHERE account_id =1;

--How can I exec the commit only if everything is ok?
COMMIT;

只有当余额>100时才会执行第一个查询。

但是,只有在前一个查询减少了余额时,才应该执行第二个查询(即第二次更新)。我怎样才能自动检查这个?

此外,COMMIT;仅当前 2 个查询已完成其工作时才必须执行。

如何实现?

(我也在使用 PHP,但我认为使用 sql 可以轻松解决这个问题。我错了吗?)

【问题讨论】:

  • 根据CONTINUE HANDLER定义,在其代码中设置一些标志变量,在语句执行后分析其值是否先前语句产生了一些错误/警告。不要忘记从第一个查询中删除 WHERE,而是将CHECK (balance >= 0) 约束添加到允许检测问题的表定义中。
  • 只有当余额>100时才会执行第一个查询。这是错误的!!!无论如何都会执行查询。它仅在满足条件时才更改数据 - 这是真的。
  • @Akina 当然,我的意思是仅当余额>100 时才会执行更改

标签: php mysql sql transactions


【解决方案1】:

将操作作为单个查询执行,而不是作为查询包:

UPDATE accounts t1
CROSS JOIN accounts t2
SET t1.balance = (t1.balance-100),
    t2.balance = (t2.balance+100)
WHERE t1.account_id = 2 AND t1.balance>100
  AND t2.balance_id = 1;

-- or

UPDATE accounts
SET balance = balance + CASE account_id WHEN 1 THEN 100
                                        WHEN 2 THEN -100 END
WHERE account_id IN (1,2);

而且你根本不需要在交易中。


您还可以检查先前查询更改的行数(实际上是在磁盘上,而不是正式地),并在第二次查询中考虑此信息:

START TRANSACTION;

UPDATE accounts
SET balance = (balance-100)
WHERE account_id = 2 AND balance>100;

UPDATE accounts
SET balance = (balance+100)
WHERE account_id =1 
  AND ROW_COUNT();  -- check does a row was altered in previous statement
                    -- if not then this statement will not alter any row too

COMMIT;

【讨论】:

  • 如果在执行第一个 set 子句时发生崩溃怎么办?整个操作回滚了吗?
  • @Umbert 在第一个选项中(在两个变体中) - 如果查询因任何原因失败,则不会更新任何行。查询不能只更新匹配的两行中的一行 - 全部或无。
  • 因此,UPDATE 中的更多 set 子句全部执行或不执行,也就是说,它们具有一种内置的转换。此外,您的第一个解决方案中的交叉联接(笛卡尔积)需要能够引用 SET 中的两个表吗?
  • @Umbert 单个查询始终是一个事务。排除 - 流宏函数(例如,LOAD DATA)。
猜你喜欢
  • 2012-10-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-01-26
  • 2022-01-02
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多