【问题标题】:How to update a non-unique column if row exists else update a different row in [MySQL]?如果行存在,如何更新非唯一列,否则更新 [MySQL] 中的不同行?
【发布时间】:2018-06-27 21:43:21
【问题描述】:

我正在尝试构建对UPDATE 的查询,如果它存在,则更新不同的行。我只希望每次执行查询时更新一行。第二个WHERE 用于查询第一部分没有返回的情况。

我希望更新一个默认值为'null' 的属性。正如我在其他帖子 (e.g.) 中看到的那样,无法使用公钥。

我可以使用 UNION 返回所需的元组,但随后无法根据需要将表达式转换为 UPDATE 查询:

(SELECT * FROM table
  WHERE (foo BETWEEN x-c AND x+c) AND (bar ..) AND column='null' LIMIT 1)
UNION
(SELECT * FROM table 
  WHERE column='null' LIMIT 1)
LIMIT 1;

这似乎总是返回第一个WHERE(如果存在),否则返回第二个WHERE

我在尝试基于计数变量设计 IF-ELSE 时收到语法错误:

SET @count=(SELECT COUNT(*) FROM table 
              WHERE (foo BETWEEN x-c AND x+c) AND (bar ..) AND column='null' LIMIT 1);
IF @count THEN
  (UPDATE table SET column='foobar'
  WHERE (foo BETWEEN x-c AND x+c) AND (bar ..) AND column='null' LIMIT 1);
ELSE
  (UPDATE table SET column='foobar'
  WHERE column='null' LIMIT 1);
END IF;

我也尝试构建子查询,但未能获得所需的行为。

我担心使用计数可能会导致出现竞争条件?不过,我不确定是否有更好的方法。

非常感谢任何帮助!

【问题讨论】:

  • 如果唯一关心的是竞争条件,为什么不在存储过程中构建所有这些,并使其成为事务?您需要将事务隔离级别设置为(可能)READ-COMMITTED,如果您需要锁定行,请添加FOR UPDATE
  • @Chosun,谢谢。我想允许对表进行并发更新,但防止尝试更新同一行。在前面的例子中,我看到整个表都被锁定了;这不是可接受的瓶颈。
  • 没问题;祝你好运!

标签: mysql sql database if-statement sql-update


【解决方案1】:

如果我理解正确,您可以使用order bylimit

update table
    set . . . 
    where column = 'null'
    order by ((foo) AND (bar)) desc
    limit 1;

desc 将首先放置符合这两个条件的行。然后将跟随其他行。 limit 选择第一个匹配项。

我想我会更倾向于分别订购这两个条件:

order by (foo) desc, (bar) desc

【讨论】:

  • 谢谢!但是,我的WHERE 条件是范围(foo between x-c and x+c)。所有行都填充了 foo、bar 等,并且会出现比最佳情况更高和更低的最坏情况行。那么这仍然适用吗? 我已经相应地更新了问题。
  • 感谢您添加的信息。一切都按要求工作。 :)
【解决方案2】:

这样的?我不能保证它很快:

update <table>
where
    column is null and <foo> and <bar>
    or not (<foo> and <bar>) and not exists (
        select 1 from <table> where column is null and <foo> and <bar>
    );

【讨论】:

    【解决方案3】:

    这是一种方法。运行第一个 UPDATE。运行后,函数ROW_COUNT() 将返回 0 或 1,具体取决于第一个 UPDATE 是否影响任何行。

    在第二个 UPDATE 中,如果 ROW_COUNT() 表明第一个 UPDATE 确实更改了某些内容,则通过设置 column=column 使更改成为空操作。

    UPDATE table SET column='foobar' WHERE (foo) AND (bar) AND column='null' LIMIT 1;
    UPDATE table SET column=IF(ROW_COUNT()=1,column,'foobar') WHERE column='null' LIMIT 1;
    

    但是,请注意,如果第一个 UPDATE 匹配行但没有进行任何净更改,则 ROW_COUNT() 返回 0,因为它找到的行已经具有值 'foobar'。

    【讨论】:

    • 嗨,这种方法似乎用column='null' 更新了第一行。我想我可能误解了什么?我想根据所有WHERE 条件进行更新,否则请使用column='null'。谢谢!
    猜你喜欢
    • 2010-12-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-07-04
    • 1970-01-01
    • 2014-07-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多