Обновите все строки в таблице с увеличивающимся текстовым значением - PullRequest
0 голосов
/ 03 февраля 2019

Как обновить столбец для каждой строки в таблице с инкрементным текстовым значением, используя SQL.

У меня есть таблица со столбцом с именем ej_number, который является уникальным идентификатором.Формат поля EJnnnn, то есть EJ, за которым следуют четыре цифры.Я импортировал данные, которые не содержат значение для ej_number, но в некоторых новых строках оно установлено.Я хочу обновить каждую строку без установленного ej_number, начиная с EJ0001.Я разрешу дублирование позже.

Сначала я сделал это в цикле в 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

Я хотел бы знать, как лучше всего это сделать без использования устаревшей функции.Я посмотрел и нашел множество построчных решений, но не смог найти альтернативы, которая бы не была построчной, возможно потому, что я не знаю достаточно, чтобы задать правильный вопрос.

1 Ответ

0 голосов
/ 03 февраля 2019

Я думаю, вы просто хотите:

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. Это сломало бы много-много-много кода.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...