【问题标题】:MySQL Get row data from Update query with LIMIT via stored procedureMySQL通过存储过程从带有LIMIT的更新查询中获取行数据
【发布时间】:2021-04-27 16:04:24
【问题描述】:

我有一个查询,它使用变量 LIMIT 更新表中的多行。我需要从更新的行中获取数据,以便知道哪些确切的行受到了影响。我写了这个简单的程序:

DELIMITER $$
CREATE PROCEDURE select_update(IN myId INT, IN myAttr VARCHAR(10), IN myAmount MEDIUMINT)
begin
  SELECT data FROM mytable WHERE id IS NULL AND attr = myAttr LIMIT myAmount;
  UPDATE mytable SET id = myId WHERE id IS NULL AND attr = myAttr LIMIT myAmount;
end$$
DELIMITER ;

此 SELECT 语句是否总是返回与 UPDATE 语句影响的完全相同的行?其他用户是否可以在此过程运行时执行查询,从而可能在 SELECT 和 UPDATE 之间更改受影响的行?

【问题讨论】:

  • 这些不在事务中。 selectupdate 之间可能会发生数据库更改。换句话说,这段代码有竞争条件。
  • @GordonLinoff 如果我在事务中调用该过程会怎样?
  • LIMIT 参数必须是文字,您不能在那里使用变量。此外,没有ORDER BYLIMIT 返回不可预测的结果,不能保证SELECTUPDATE 将处理相同的行。
  • 如果它在事务中,请将FOR UPDATE 子句添加到SELECT 查询中,这样它将锁定它搜索的所有行。
  • @Barmar,“在存储的程序中,可以使用整数值例程参数或局部变量指定 LIMIT 参数。” dev.mysql.com/doc/refman/8.0/en/select.html

标签: mysql sql


【解决方案1】:

创建一个临时表来保存要更新的行的主键。

CREATE PROCEDURE select_update(IN myId INT, IN myAttr VARCHAR(10), IN myAmount MEDIUMINT)
begin
  CREATE TEMPORARY TABLE temp_mytable AS
  SELECT pk FROM mytable WHERE id IS NULL AND attr = myAttr LIMIT myamnt;
  UPDATE mytable JOIN temp_mytable USING (pk)
  SET mytable.id = myId;
  SELECT mytable.data
  FROM mytable JOIN temp_mytable USING (pk);
end$$

【讨论】:

  • 你更喜欢这个解决方案而不是使用SELECT FOR UPDATE?另外,我们不需要ORDER BY 这个解决方案对吧?
  • 这确保了它将更新它选择的相同行,而不需要事务。如果我们不关心它更新了哪些行,我们在这里不需要 ORDER BY。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-10-14
  • 1970-01-01
  • 2014-06-17
  • 2012-07-19
  • 1970-01-01
  • 1970-01-01
  • 2018-12-27
相关资源
最近更新 更多