【问题标题】:Single SQL command to get a value, then to update that value单个 SQL 命令获取一个值,然后更新该值
【发布时间】:2020-06-30 02:19:46
【问题描述】:

主要问题

是否有一个 SQL 命令可以让我从表行中选择一个值,并在同一个 SQL 命令中更新该值?

更详细的问题

我在一个电子商务网站上工作,我在该网站上使用 MYSQL 数据库,该数据库有一个 products 表,其中包含产品列表,等等。

此表中包含一个quantity 字段和一个sold 字段。

quantity 表示该产品的生产总量,sold 是该产品的当前销售量/用户购买量。

因此,如果 sold 字段与 quantity 匹配,我想更新前端 HTML 以指示它缺货。

所以当用户购买“x”数量的产品时,我知道我可以执行以下两个 SQL 命令来更新 sold 字段:

SELECT sold FROM products WHERE productID = ?

我会用刚刚购买的产品的 ID 回填 ?。

获得sold 值后,我将添加用户刚刚购买的金额,然后执行更新命令,例如:

UPDATE products SET sold = ? WHERE productID = ?

执行两个不同的 SQL 命令是最好的方法吗?还是将其组合在一个 SQL 命令中更好?

另外,我怎样才能最好地锁定这个特定的product 使用 SQL 语句在表中,以便如果用户 A 购买产品“xyz”同时用户 B 购买相同的产品没有我要更新的 sold 字段的竞争条件?

更新: 我正在使用java与MYSQL数据库进行通信。

【问题讨论】:

  • 你的编程语言是什么?
  • 我正在使用 Java 与 MySQL 数据库通信。
  • 你使用的是 Spring、纯 JDBC 还是其他?
  • 您是否尝试过仅增加价值?更新产品 SET 已售出 = 已售出 + ? WHERE productID = ?

标签: java mysql sql


【解决方案1】:

最好将其作为两个单独的 SQL 语句来执行。事实上,这是必要的。

你这样做:

START TRANSACTION; 

SELECT sold FROM products WHERE productID = ? FOR UPDATE;

UPDATE products SET sold = ? WHERE productID = ?;

COMMIT;

(这些是 SQL 语句,但将其调整为 Java 或任何其他编程语言取决于您。可能还有用于启动事务和提交的 Java 方法,它们做同样的事情,所以没关系使用它们。)

FOR UPDATE 在检查的行上获得一个锁,与UPDATE 获得的锁类型相同。锁一直保持到事务提交为止。因此,您可以更新它而无需担心并发会话的竞争条件。

但请确保及时执行 SELECT、UPDATE 和 COMMIT。我看到许多开发人员执行 SELECT...FOR UPDATE,然后在这和 UPDATE 之间,他们的应用程序执行了一堆其他代码,包括可能需要一段时间的事情,比如调用其他服务的 API。您希望立即到达 COMMIT,因为锁会使其他并发会话等待。

【讨论】:

  • OP 使用的是 Java,而不是原始 MySQL。
  • 没关系,有启动和提交事务的方法。我只是在演示操作的顺序,而不是调用它们的文字代码。任何提出这个问题的人都应该能够以各自的语言和界面查找如何做到这一点。
  • @Strawberry,我想我可以猜到你的评论。可以在不先获取值的情况下更新,例如到SET sold = sold + 10。但是应用程序可能需要显示旧值和新值来报告更新。或者在更新之前根据一些配置的界限检查值。获取和更新还有其他可能的原因。 OP 询问如何获取值并更新它,这就是我的回答。
  • @Strawberry,欢迎您发表自己的答案。
  • @all Bill Karwin 正是我所需要的。我知道如何进行 SQL 选择,然后对检索到的参数进行操作,然后进行更新。我不知道是否有更好的方法,更具体地说,一个可以做到这一点的命令,和如何锁定有问题的product 行以避免竞争条件。我将他的回复标记为答案,因为我已经按照他在 Java 中推荐的内容进行了操作,并且效果很好。
猜你喜欢
  • 2021-08-27
  • 1970-01-01
  • 2019-09-26
  • 1970-01-01
  • 1970-01-01
  • 2014-11-28
  • 2014-01-04
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多