2009-09-08 7 views
5

J'ai une table avec une liste d'enregistrements et une colonne appelée order. J'ai un script AJAX pour glisser et déposer les lignes de la table vers le haut ou vers le bas que je veux utiliser pour effectuer une requête, en réorganisant les lignes comme elles ont été déplacées.SQL Mass Réorganisation des lignes

En PHP, j'effectue une requête pour obtenir l'ordre actuel des enregistrements. par exemple 1, 2, 3, 4 La fonction AJAX passe le nouvel ordre après que le glisser/déposer soit terminé, par exemple 3, 1, 2, 4

Existe-t-il un moyen simple de réorganiser les enregistrements en une fois? , basé sur les nouvelles valeurs? La seule autre alternative que je peux voir est de boucler par des instructions UPDATE par exemple SET order = 1 où order = 3

Mais sûrement cela aboutirait à 2 enregistrements ayant la même valeur? Excuses, je sais que cette description peut être légèrement déroutante.

Répondre

1

Vous voulez vraiment revenir en arrière et regarder les résultats de la fonction ajax. Voyez si vous pouvez obtenir une liste d'éléments réorganisés au lieu de simplement le nouvel ordre de liste.

Vous pouvez écrire une fonction (en C#/VB) pour déterminer ceci pour vous dans le code donné les listes avant et après. Une fois les modifications de delta effectuées, vous pouvez émettre une transaction de mise à jour avec une commande de mise à jour par réorganisation.

Si vous voulez travailler avec juste la nouvelle commande. Essayez d'ajouter une nouvelle colonne appelée neworder et mettez-la à jour. Puis vrac update currentcolumn = newcolumn une fois fait une boucle.

+0

Cela fonctionnerait, mais vous voulez faire toutes les mises à jour dans une seule transaction, en cas plusieurs clients mettent à jour la commande en même temps. – MusiGenesis

6

L'ordre ne devrait pas être votre clé primaire; faites les mises à jour en utilisant la clé primaire dans la clause where.

Vous pouvez tout faire en une seule requête en utilisant une instruction CASE assez longue, si vous le souhaitez vraiment. Exemple:

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) 

(Rappelez-vous que les instructions SQL se comportent comme si elles changent toutes les valeurs en même temps, de sorte que ne fera pas quelque chose comme le changement de 1 à 2, puis 3, etc.)

+0

Ceci est une solution commune. Dans les cas où il y a beaucoup de rangs après celui qui est réorganisé, cela peut devenir lourd. Dans ce cas, je préfère avoir une colonne 'next' à la place, et la traiter comme une liste chaînée. Cela réduit toute opération de réorganisation possible à un maximum de trois mises à jour de ligne. –

+0

@Brent Rockwood en effet. Une autre approche (souvent plus simple à migrer) consiste à utiliser l'ordre 100, 200, 300, puis vous pouvez facilement insérer l'ordre 150. Cela réduit considérablement le besoin de renuméroter. – derobert

1

Si vous connaissez le nouvelle position de ligne, vous pouvez le faire:

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

vous pouvez faire quelque chose comme

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; 

(non testé, CECI EST JUSTE A POINTER)

Questions connexes