Обновление нескольких строк, которые конфликтуют с уникальным индексом

Я использую Microsoft SQL Server, и у меня есть сценарий master-detail, в котором мне нужно хранить порядок деталей. Итак, в таблице Detail у меня есть ID, MasterID, Position и некоторые другие столбцы. Также есть уникальный индекс по MasterID и Position. Работает нормально, кроме одного случая: когда у меня есть какие-то существующие реквизиты и я меняю их порядок. Например, когда я меняю деталь в позиции 3 на деталь в позиции 2. Когда я сохраняю деталь в позиции 2 (которая в базе данных имеет позицию, равную 3), SQL Server протестует, потому что ограничение уникальности индекса.

Как решить эту проблему разумным путем?

Заранее спасибо
Лукаш Глаз


person GUZ    schedule 07.04.2010    source источник


Ответы (2)


Это классическая проблема, и ответ прост: если вы хотите переместить элемент 3 на позицию 2, вы должны сначала изменить столбец сортировки 2 на временное число (например, 99). Итак, это выглядит так:

Move 2 to 99
Move 3 to 2
Move 99 to 3

Однако вы должны быть осторожны, чтобы ваше временное значение никогда не использовалось в обычной обработке, и чтобы вы учитывали несколько потоков, если это применимо.

Обновление: Кстати, один из способов решить проблему «несколько пользователей могут изменить порядок» — сделать то, что делаю я: дать каждому пользователю числовой идентификатор, а затем добавить его к временному номеру (мой идентификатор персонала на самом деле является идентификатором поля уникальной идентификации из таблицы персонала, используемой для входа в систему). Так, например, если ваши позиции никогда не будут отрицательными, вы можете использовать -1000 - UserID в качестве временного значения. Однако поверьте мне в одном: вы не хотите просто предположить, что у вас никогда не будет столкновения. Если вы так думаете и что-то действительно происходит, отладить будет очень сложно!

Обновление: GUZ указывает, что его пользователи могли изменить порядок всего набора позиций и отправить их как пакет — это не просто переключение двух записей. Тогда вы можете подойти к этому одним из двух способов.

Во-первых, вы можете изменить существующие поля сортировки всего набора на новый набор неконфликтующих значений (например, -100 - (staffID * maxSetSize) + существующийOrderVal), а затем перейти от записи к записи и изменить каждую запись на новую. Ценность заказа.

Или вы могли бы рассматривать это как пузырьковую сортировку в массиве, где значение orderVal эквивалентно индексу вашего массива. Либо это имеет для вас смысл (и очевидно), либо вам следует придерживаться решения 1 (которое в любом случае проще).

person Mark Brittingham    schedule 07.04.2010
comment
Я как раз собирался опубликовать этот ответ. Обгони меня на 30 секунд. - person AllenG; 07.04.2010
comment
@AllenG - Я слышу вас ... Я не могу сказать вам, сколько раз я нажимал кнопку «Отправить» только для того, чтобы обнаружить, что меня избили до удара. Есть немного получить его там первое давление на SO. - person Mark Brittingham; 08.04.2010
comment
Проблема в том, что пользователь может сделать много изменений в области порядка деталей, а затем эти изменения сохраняются в одном пакете. - person GUZ; 08.04.2010
comment
ГУЗ - тогда вам просто нужно работать в обратном направлении. Смотрите мое обновление выше. - person Mark Brittingham; 08.04.2010

вы можете просто удалить уникальное ограничение (но оставить ключ индекса) в столбце заказа и при необходимости обеспечить уникальность своего кода.

person chris    schedule 07.04.2010
comment
Исходя из фона EDI, я могу сказать, что это не всегда практично. Обычно это срабатывает, но бывают случаи, когда проблем больше, чем пользы. Решение Марка работает очень хорошо. - person AllenG; 07.04.2010