2009-09-08 20 views
5

Mam tabelę z listą rekordów i kolumną o nazwie order. Mam skrypt AJAX do przeciągania i upuszczania wierszy tabel w górę lub w dół, które chcę użyć do wykonania zapytania, zmieniając kolejność wierszy po ich przeciągnięciu.Ponowne porządkowanie SQL wierszy

W PHP wykonuję zapytanie, aby uzyskać bieżącą kolejność rekordów. np. 1, 2, 3, 4 Funkcja AJAX przekazuje nowe zamówienie po zakończeniu przeciągania/upuszczania, np. 3, 1, 2, 4

Czy istnieje prosty sposób na ponowne zamówienie rekordów za jednym razem , na podstawie nowych wartości? Jedyną inną alternatywą jaką widzę jest pętla instrukcji UPDATE, np. SET order = 1 gdzie order = 3

Ale na pewno spowodowałoby to 2 rekordy o tej samej wartości?

Przepraszam, wiem, że ten opis może być nieco mylący.

Odpowiedz

1

Naprawdę chcesz wrócić i spojrzeć na wyniki funkcji ajax. Sprawdź, czy możesz uzyskać listę uporządkowanych elementów zamiast nowej listy.

Można napisać funkcję (w języku C#/VB), aby ustalić to za pomocą kodu podanego przed i po liście. Po wprowadzeniu zmian w wartości delta można wydać transakcję aktualizacji za pomocą jednego polecenia aktualizacji na każdy kolejny.

Jeśli chcesz pracować z nowym zamówieniem. Spróbuj dodać nową kolumnę o nazwie neworder i zaktualizuj ją. Następnie zbiorcza aktualizacja currentcolumn = newcolumn po wykonaniu pętli.

+0

to będzie działać, ale tylko chcesz zrobić wszystkie aktualizacje w ramach pojedynczej transakcji, w przypadku wielu klientów aktualizuje zamówienie w tym samym czasie. – MusiGenesis

6

Zamówienie nie powinno być Twoim kluczem podstawowym; aktualizuj za pomocą klucza podstawowego w klauzuli where.

Możesz zrobić to wszystko w jednym zapytaniu, używając dość długiej instrukcji CASE, jeśli naprawdę chcesz. Przykład:

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) 

(Pamiętaj, że SQL zachowują się tak, jakby jednocześnie zmienić wszystkie wartości, tak że nie zrobi czegoś takiego zmiany 1 do 2, potem 3, itd.)

+0

To jest typowe rozwiązanie. W przypadkach, gdy istnieje wiele wierszy po zmianie, może to być nieporęczne. W takim przypadku wolę mieć zamiast tego "następną" kolumnę i traktować ją jak połączoną listę. Zmniejsza to wszelkie możliwe zmiany kolejności operacji do maksymalnie trzech aktualizacji wiersza. –

+0

@Brent Rockwood naprawdę. Innym podejściem (często łatwiejszym do przeprowadzenia migracji) jest użycie zlecenia 100, 200, 300, a następnie łatwe wprowadzenie zamówienia 150. To znacznie zmniejsza potrzebę ponownej numeracji. – derobert

1

Jeśli znasz nowa pozycja rząd może to zrobić:

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

można zrobić coś

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; 

(NIETESTOWANY, to tylko wskaźnik)