【问题标题】:Update all rows in a table with incrementing text value使用递增的文本值更新表中的所有行
【发布时间】:2019-02-03 00:04:19
【问题描述】:

如何使用 SQL 使用递增的文本值更新表中每一行的列。

我有一个表,其中有一个名为 ej_number 的列,它是一个唯一标识符。字段格式为EJnnnn,即EJ 后跟四位数字。我已导入不包含 ej_number 值的数据,但某些新行确实设置了它。我想从 EJ0001 开始更新没有设置 ej_number 的每一行。稍后我会解决重复问题。

我先是用PHP循环做的,但是意识到服务器会因为行数而超时,所以我决定用SQL做。

我的第一个想法是使用循环,但我的研究发现不推荐逐行更新,尤其是我能看到的唯一方法是使用游标,这也是不推荐的。

我能够在单个语句中完成 - 下面的代码有效,但它会生成一个警告(使用 MySQL Workbench)。

SET @next_number = 0;
UPDATE ej_details
    SET ej_number = CASE
        WHEN ej_number IS NULL THEN (
            CONCAT('EJ', LPAD((@next_number:=@next_number+1), 4, '0')))
        ELSE ej_number
    END;

该语句执行我想要的操作,但会生成此警告:

692 行受影响,1 个警告:1287 在表达式中设置用户变量已弃用,将在未来版本中删除。请改为在单独的语句中设置变量。匹配行:692 更改:692 警告:1

我想知道如何在不使用已弃用功能的情况下最好地做到这一点。我查看并找到了大量的逐行解决方案,但看不到不是逐行的替代方案,可能是因为我没有足够的知识来提出正确的问题。

【问题讨论】:

  • 你是如何从 PHP 中执行这个 SQL 代码的?它可能需要 2 个单独的查询(SET,然后是 UPDATE
  • 抱歉,我可能不够清楚。这不是我在 PHP 中执行的代码,它使用 PDO(准备好的语句)并且是逐行循环的,而且非常慢。

标签: mysql sql loops


【解决方案1】:

我想你只是想要:

SET @next_number = 0;

UPDATE ej_details
    SET ej_number = CONCAT('EJ',
                           LPAD( (@next_number:=@next_number+1), 4, '0'
                               )
                          )
    WHERE ej_number IS NULL;

这样更简单,但不会改变错误。

如果您想在一次调用中执行此操作,那么:

UPDATE ej_details CROSS JOIN
       (SELECT @next_number := 0) params
    SET ej_number = CONCAT('EJ',
                           LPAD( (@next_number:=@next_number+1), 4, '0'
                               )
                          )
    WHERE ej_number IS NULL;

不幸的是,如果该列被声明为unique,那么您无法“稍后”解析重复值。

如果您想在没有错误的情况下解决此问题,则需要一个主键/唯一列:

UPDATE ej_details ed JOIN
       (SELECT ed.*,
               ROW_NUMBER() OVER (ORDER BY ej_number) as seqnum
        FROM ej_details ed2
        WHERE ej_number IS NULL
       ) ed2
       ON ed2.? = ed.?  -- the primary key goes here
    SET ed.ej_number = CONCAT('EJ', LPAD(ed2.seqnum, 4, '0')
                             );

但是,此版本不向后兼容。

如果他们真的从 MySQL 9 中删除了变量,我会感到惊讶。这会破坏很多很多代码。

【讨论】:

  • 谢谢,这回答了我的问题。我需要掌握联接。 ej_number 意味着是唯一的,但它还没有被声明为这样。有一个唯一的 id 列可用于最后一个示例。我不担心向后兼容性。
猜你喜欢
  • 2011-12-20
  • 1970-01-01
  • 1970-01-01
  • 2012-10-02
  • 2012-08-11
  • 1970-01-01
  • 2012-10-20
  • 1970-01-01
  • 2012-07-29
相关资源
最近更新 更多