如何检查先前的查询是不是正确执行?

Posted

技术标签:

【中文标题】如何检查先前的查询是不是正确执行?【英文标题】: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 时才会执行更改 【参考方案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)。

以上是关于如何检查先前的查询是不是正确执行?的主要内容,如果未能解决你的问题,请参考以下文章

如何检查 QProcess 是不是正确执行?

我是不是正确执行这些步骤来检查用户的应用内结算订阅?

单元测试检查数据库查询是不是正确——可以模拟啥?

删除某数据库下所有的表

查询 Google Play Developer API 时出现意外错误。请检查您是不是使用了正确的服务帐号

如何使用 Oracle 正确执行 SELECT 查询的性能测试?