Повторяющаяся запись «1-1110» для ключа «INDEX» при удалении элемента из индекса - PullRequest
0 голосов
/ 17 мая 2019

У меня есть запрос на обновление индекса, если что-то добавлено между

update My_Table
     set NS_LEFT = NS_LEFT + 10
     where NS_THREAD = parentThread and NS_LEFT > oldRight
     order by NS_LEFT desc

Работает нормально -

Теперь я, если мне нужно что-то удалить между, тогда я использую запрос какниже

update My_Table
    set NS_LEFT = NS_LEFT - 10
    where NS_THREAD = parentThread and NS_LEFT > oldRight
    order by NS_LEFT desc

Не работает и выдает ошибку дубликата индекса -

[Код: 1062, Состояние SQL: 23000] (conn = 1517) Повторяющаяся запись '1-1110 'для ключа' INDEX '

Индекс (NS_THREAD, NS_LEFT)

Как решить для удаления элемента

Примечание Это мойОбойти для MariaDB только для других других баз данных, работающих без OrderBy (почему .. это все еще открытый вопрос для меня)

Ответы [ 2 ]

2 голосов
/ 18 мая 2019

То, что я делал в прошлом, когда управлял ордером, - это не вариант - выполнить два обновления. Первый сдвигает группу вверх за пределы любых используемых в настоящее время значений, обеспечивая отсутствие коллизий. Второй затем сдвигает их туда, где они должны быть. В общем виде идея может быть проиллюстрирована этим:

UPDATE aTable SET somevalue = somevalue + 10000 WHERE somevalue > x;
UPDATE aTable SET somevalue = somevalue - 10000 - y WHERE somevalue > x + 10000;

«10000» - это просто значение, которое сдвинет диапазон после столкновения, y - это величина, которую вы действительно хотите сместить. Очевидно, что если уже есть значения около 10000, число должно быть другим. Чтобы избежать необходимости запрашивать безопасное значение, есть еще один вариант, если конструкция позволяет ....

Если отрицательные значения не используются, а дизайн таблицы допускает отрицательные числа, эту версию процесса применить немного проще:

UPDATE aTable SET somevalue = somevalue * -1 WHERE somevalue > x;
UPDATE aTable SET somevalue = (somevalue * -1) - y WHERE somevalue < 0; 

Это предполагает, что обычно нет отрицательных значений, и для безопасности обновления должны выполняться в транзакции (вместе с первоначальным удалением), чтобы потенциальные параллельные приложения этого решения не сталкивались. (Изменить: Обратите внимание, что требование транзакций / параллелизма распространяется на обе формы, которые я представил.)

Редактировать: О, я только что заметил, что ответ Гордона был довольно похож ... голые знаки минус выглядели как пятна на моем экране. Если Гордон не работает, это тоже не будет.

1 голос
/ 17 мая 2019

Это происходит. Одно из решений - сделать два обновления:

update My_Table
    set NS_LEFT = - (NS_LEFT - 10)
    where NS_THREAD = parentThread and NS_LEFT > oldRight
    order by NS_LEFT desc;

update My_Table
    set NS_LEFT = - NS_LEFT
    where NS_THREAD = parentThread and NS_LEFT < 0;
...