如何使用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
我想知道如何最好地做到这一点而不使用不推荐使用的功能。我查看并找到了大量的逐行解决方案,但看不到不是逐行的替代方案,可能是因为我不知道该问什么。
答案 0 :(得分:0)
我想你只是想要
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中删除了变量,我会感到惊讶。这会破坏很多代码。