如何检查先前的查询是不是正确执行?
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)。以上是关于如何检查先前的查询是不是正确执行?的主要内容,如果未能解决你的问题,请参考以下文章