【问题标题】:MySQL Table won't update multiple rowsMySQL 表不会更新多行
【发布时间】:2014-05-08 06:31:10
【问题描述】:

我不确定,但我认为我在此查询中有错误:

UPDATE product_discount SET price = '10,15' WHERE key_id = '1,2' 

我不知道为什么,但它只更新列中的数字 10 并跳过 15。

【问题讨论】:

  • 价格的数据类型是什么?
  • price 列的数据类型是什么?
  • @Kermit 抱歉它是十进制
  • 没有。它必须是 id 为 1 的一行有 10 个,而 id 为 2 的第二行有 15 个
  • Multiple Updates in MySQL 的可能重复项

标签: mysql sql sql-update


【解决方案1】:

我认为这就是你所需要的(假设Price 应该是 10 而key_id = 1):

UPDATE product_discount SET price = CASE WHEN key_id = 1 THEN 10 ELSE 15 END
WHERE key_id IN (1,2) 

【讨论】:

  • 我不确定那里需要CASE
  • 如果 OP 根据 key_id 需要不同的 Price 值,那么我们需要一个 CASE 表达式,否则不需要。根据他/她的 cmets,我认为 OP 需要 10 个 key_id = 1。
  • @Kaf,你的回答很好,我也会这样做,但我认为最后一个 WHERE 部分不需要。
  • 这适用于 OP 询问的特定情况,但最好为应该更新的每一行使用明确的情况,而不是 ELSE 15,以防新手没有立即看到如何扩展它以更新> 2行。 (例如:@Rahul 上面的评论...)
【解决方案2】:

你可以试试this answer建议的方法:

INSERT INTO product_discount (key_id, price) 
VALUES (1, 10), (2, 15)
ON DUPLICATE KEY UPDATE price=VALUES(price);

不过,请务必阅读链接的答案以了解一些注意事项;例如,这仅在以下情况下有效:

  • key_id 上存在唯一键约束(例如,它是主键)
  • 您知道具有这些 id 的行已经存在,或者如果您提供的 id 在表中不存在,您不介意插入新行

尽管在使用上有这些限制,但与CASE 语句相比,此方法的显着优势在于更好的可读性和参数化。例如,在 Python 中,您将使用MySQLdb 模块执行@Kaf 的答案中给出的查询:

query = """UPDATE product_discount SET price = CASE 
    WHEN key_id = %s THEN %s ELSE %s 
    END 
WHERE ID IN (%s, %s);"""

params = (1, 10, 15, 1, 2)

cursor.execute(query, params)

需要多长时间才能从 params 元组中找出您想要更新哪些值,以及它们的值应该是什么?如果你想更新超过两行怎么办?您不仅需要为 N 行的每个用例重写 query,而且如果 N 只是少数,params 元组就会变成难以辨认的垃圾。您可以编写一些辅助函数来根据您需要执行的更新次数来格式化queryparams,但这需要多长时间?理解起来有多容易?你会在所有这些额外的代码行中引入多少错误机会?

另一方面,以下是使用 INSERT ... ON DUPLICATE KEY UPDATE 方法的方法:

query = """INSERT INTO product_discount (key_id, price) VALUES (%s, %s)
ON DUPLICATE KEY UPDATE price=VALUES(price);"""
params = [(1, 10),
          (2, 15),
          ]
cursor.executemany(query, params)

键值关系清晰易读。如果需要更新更多行,可以将更多键值元组添加到 params 列表中。这不是每个场景的完美解决方案,但对于特定(我认为,非常常见的)场景,它比 CASE 更好的解决方案。

【讨论】:

  • @xQbert 这是一个INSERT 声明,但仍然是一种更新方法。我添加了一些细节:何时以及为什么您可能更喜欢它而不是 UPDATE ... CASE 方法。
  • 最初错过了ON DUPLICATE KEY UPDATE price=VALUES(price);。 +1 用于后续和更多细节。我看到的风险是,如果有人传入了错误的参数,您可能最终会更新现有记录,而您确实打算创建一个;并且不会抛出任何错误。虽然可读性可能会提高,但某些环境可能难以为更新编写插入语句。但是由于开发人员应该看到ON DUPLICATE KEY UPDATE price=VALUES(price); 的风险得到了缓解。在一定程度上。
  • 我想我会同意 UPDATE ... CASE 方法更安全,只要可以残酷地明确。最好的事情显然是支持 MySQL 中的多个更新的语法。
  • 就此而言,using a mapping table 可能是最安全和最具可扩展性的方法,但代价是需要几个额外的步骤。
【解决方案3】:

我认为 Kaf 很接近,但有时 key_id 可以是 3 或 4 或 5 对吗?因此,您需要确保这些值不会更改为 15。这应该可以解决问题!

UPDATE product_discount 
SET price = CASE WHEN key_id = 1 THEN 10 
                 WHEN key_id = 2 THEN 15 
                 ELSE price END

【讨论】:

  • Kaf 已经正确,因为 key_id 不是 1 和 2 的行不会被更新。
  • 其实你是对的。因为只有 1 和 2 有一个 where 子句,所以它应该可以工作。
  • 这应该也可以,但我怀疑如果你有几百万行,他将只更新必要的行,而这将更新 all 行。
  • 非常感谢你们,非常感谢你们的帮助!!!你帮了我很多!
【解决方案4】:

我觉得你想要做的是

当 key_id = 1 时更新价格 = 10
(或)
当 key_id = 2 时价格 =15。

在这种情况下,就这样做

UPDATE product_discount SET price = 
CASE WHEN key_id = 1 THEN 10 
WHEN key_id = 2 THEN 15
ELSE price
END

【讨论】:

  • @JoachimIsaksson,完全是我的坏。感谢您指出错误。更新答案并一起摆弄。
  • 这应该可以,但我怀疑如果你有几百万行,Kaf 的答案将只更新必要的行,而这将更新 all 行(或至少不使用查找要更新的行的索引)
  • 那么@JoachimIsaksson 的实际答案是什么,因为我非常需要它
  • @user3465207,我觉得 Kafs 的回答对你的要求来说很好。唯一的区别 b/w 卡夫和我的答案是 where 子句。您可以使用此评论链中提到的小提琴进行测试。
猜你喜欢
  • 1970-01-01
  • 2012-12-22
  • 1970-01-01
  • 1970-01-01
  • 2023-04-02
  • 1970-01-01
  • 1970-01-01
  • 2012-05-03
相关资源
最近更新 更多