2009-09-08 22 views
5

Tengo una tabla con una lista de registros y una columna llamada orden. Tengo un script AJAX para arrastrar y soltar las filas de la tabla hacia arriba o hacia abajo que quiero usar para realizar una consulta, reordenando las filas a medida que se arrastran.SQL Reordenamiento masivo de filas

En el PHP, puedo realizar una consulta para obtener el orden actual de los registros. por ejemplo, 1, 2, 3, 4 La función AJAX pasa el nuevo pedido después de que se completa la operación de arrastrar/soltar, por ej. 3, 1, 2, 4

¿Existe una manera simple de reordenar los registros de una sola vez? , basado en los nuevos valores? La única alternativa que veo es un bucle a través UPDATE por ejemplo, orden del set = 1 donde el orden = 3

Pero sin duda esto se traduciría en 2 registros tienen el mismo valor?

Disculpas, sé que esta descripción puede ser un poco confuso.

Respuesta

1

que realmente quiere volver atrás y mirar los resultados de la función ajax. Vea si puede obtener una lista de elementos reordenados en lugar de solo el nuevo orden de la lista.

Se podría escribir una función (en C#/VB) para determinar esto para usted en el código dado antes y después de las listas. Una vez que tenga los cambios delta, puede emitir una transacción de actualización con un comando de actualización por pedido nuevo.

Si desea trabajar solo con la nueva orden. Intente agregar una nueva columna llamada neworder y actualícela. Luego, la actualización masiva currentcolumn = newcolumn una vez hecho el bucle.

+0

Esto funcionaría, pero que querría hacer todas las actualizaciones dentro de una sola transacción, en el caso varios clientes están actualizando el pedido al mismo tiempo. – MusiGenesis

6

El pedido no debe ser su clave principal; hacer las actualizaciones usando la clave primaria en la cláusula where.

usted puede hacerlo todo en una consulta mediante una instrucción CASE bastante largo, si realmente desea. Ejemplo:

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) 

(Recuerde que las sentencias SQL se comportan como si cambian todos los valores al mismo tiempo, por lo que no va a hacer algo como el cambio del 1 al 2, luego a 3, etc.)

+0

Esta es una solución común. En los casos en que hay muchas filas después de la que se reordenó, esto puede volverse difícil de manejar. En ese caso, prefiero tener una 'próxima' columna y tratarla como una lista vinculada. Esto reduce cualquier posible operación de reordenamiento a un máximo de tres actualizaciones de fila. –

+0

@Brent Rockwood de hecho. Otro enfoque (a menudo más fácil de migrar también) es usar la orden 100, 200, 300, luego puede insertar fácilmente la orden 150. Esto reduce en gran medida la necesidad de volver a numerar. – derobert

1

Si conoce la nueva posición de la fila se puede hacer esto:

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

se podría hacer algo como

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; 

(no comprobado, esto es sólo un PUNTERO)