2009-09-08 2 views
5

У меня есть таблица со списком записей и столбец, называемый порядком. У меня есть сценарий AJAX для перетаскивания строк таблицы вверх или вниз, которые я хочу использовать для выполнения запроса, переупорядочивая строки по мере их перетаскивания.SQL Mass Переупорядочение строк

В PHP я выполняю запрос, чтобы получить текущий порядок записей. например, 1, 2, 3, 4 Функция AJAX передает новый порядок после завершения перетаскивания, например 3, 1, 2, 4

Есть ли простой способ переупорядочить записи за один раз , основываясь на новых значениях? Единственная альтернатива, которую я вижу, - это цикл через инструкции UPDATE, например SET order = 1, где order = 3

Но, конечно, это приведет к тому, что 2 записи имеют одинаковое значение?

Извинения, я знаю, это описание может быть немного запутанным.

ответ

1

Вы действительно хотите вернуться назад и посмотреть результаты функции ajax. Посмотрите, можете ли вы получить список переупорядоченных элементов, а не только новый порядок списка.

Вы можете написать функцию (в C#/VB), чтобы определить это для вас в коде с учетом списков до и после. После изменения дельта вы можете выполнить транзакцию обновления с одной командой обновления для каждого изменения порядка.

Если вы хотите работать только с новым заказом. Попробуйте добавить новый столбец с именем neworder и обновите его. Затем массовое обновление currentcolumn = newcolumn после завершения цикла.

+0

Это будет работать, но вы хотите сделать все обновления в рамках одной сделки, в случае несколько клиентов обновляют заказ одновременно. – MusiGenesis

6

Заказ не должен быть вашим первичным ключом; выполните обновления, используя первичный ключ в предложении where.

Вы можете сделать все это одним запросом, используя довольно длинный оператор CASE, если вы действительно этого хотите. Пример:

UPDATE foo 
    SET order = CASE order 
    WHEN 1 THEN 2 
    WHEN 2 THEN 3 
    WHEN 3 THEN 4 
    WHEN 4 THEN 5 
    END 
WHERE order IN (1,2,3,4) 

(Помните, что SQL заявления ведут себя так, как будто они изменяют все значения одновременно, так что не будет делать что-то вроде изменения от 1 до 2, затем 3 и т.д.)

+0

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

+0

@Brent Роквуд действительно. Другой подход (часто проще переносить) - использовать порядок 100, 200, 300, тогда вы можете легко вставить заказ 150. Это значительно сокращает необходимость перенумеровать. – derobert

1

Если вы знаете, новое положение строки вы можете сделать это:

CREATE PROCEDURE [proc_UpdateCountryRowOrder] 
    @ID UNIQUEIDENTIFIER, 
    @NewPosition INT 
AS 

SET NOCOUNT ON 

DECLARE @CurrentPosition INT 
DECLARE @MaximumPosition INT 

IF (@NewPosition < 1) SET @NewPosition = 1 

SELECT @CurrentPosition = [Countries].[Order] 
FROM [Countries] 
WHERE [Countries].[ID] = @ID 

SELECT @MaximumPosition = MAX([Countries].[Order]) 
FROM [Countries] 

IF (@NewPosition > @MaximumPosition) SET @NewPosition = @MaximumPosition 

IF (@NewPosition <> @CurrentPosition) 
BEGIN 
    IF (@NewPosition < @CurrentPosition) 
    BEGIN 
     BEGIN TRAN 

     UPDATE [Countries] 
     SET [Countries].[Order] = [Countries].[Order] + 1 
     WHERE [Countries].[Order] >= @NewPosition 
     AND [Countries].[Order] < @CurrentPosition 

     UPDATE [Countries] 
     SET [Countries].[Order] = @NewPosition 
     WHERE ID = @ID 

     COMMIT TRAN 
    END 
    ELSE 
    BEGIN 
     BEGIN TRAN 

     UPDATE [Countries] 
     SET [Countries].[Order] = [Countries].[Order] - 1 
     WHERE [Countries].[Order] <= @NewPosition 
     AND [Countries].[Order] > @CurrentPosition 

     UPDATE [Countries] 
     SET [Countries].[Order] = @NewPosition 
     WHERE ID = @ID 

     COMMIT TRAN 
    END 
END 
GO 
0

вы могли бы сделать что-то вроде

BEGIN 
UPDATE Table SET order = order + 1 WHERE order >= new_pos 
UPDATE Table SET order = new_pos WHERE order = old_pos 
UPDATE Table SET order = order - 1 WHERE order < old_pos AND order > new_pos 
COMMIT; 

(UNTESTED, ЭТО ПРОСТО POINTER)

Смежные вопросы