2009-09-08 61 views
5

我有一個包含記錄列表的表和一個名爲order的列。我有一個AJAX腳本來上下拖放表格行,我想用它來執行查詢,重新排序拖動行的順序。SQL Mass重新排序的行

在PHP中,我執行查詢以獲取記錄的當前順序。例如1,2,3,4 4 拖放完成後AJAX功能通過新訂單,例如3,1,2,4,0

是否有一種簡單的方法來一次性重新排序記錄,基於新的價值?我能看到的唯一的另一種選擇是循環UPDATE語句,例如SET order = 1,其中order = 3

但是肯定會導致2條記錄具有相同的值?

道歉,我知道這個描述可能會有些混亂。

回答

1

你真的想回頭看看ajax函數的結果。看看你是否可以得到重新排序的元素列表,而不僅僅是新的列表順序。

您可以編寫一個函數(在C#/ VB中)以給定前後列表的代碼來爲您確定。一旦你有增量更改,你可以發出一個更新事務,每次重新排序一個更新命令。

如果您只想處理新訂單。嘗試添加一個名爲neworder的新列並更新它。然後在完成循環後批量更新currentcolumn = newcolumn。

+0

這會工作,但你想要做一個單一的事務中的所有更新,萬一多個客戶正在同時更新訂單。 – MusiGenesis 2009-09-08 13:01:33

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

這是一個常用的解決方案。在重新排序之後有很多行的情況下,這可能會變得笨拙。在這種情況下,我寧願有一個'下一個'列,而是把它當作一個鏈表。這將任何可能的重新排序操作減少到最多三個行更新。 – 2013-09-07 20:24:18

+0

@布倫洛克伍德的確如此。另一種方法(通常更簡單地遷移)是使用訂單100,200,300,那麼您可以輕鬆插入訂單150.這大大減少了重新編號的需要。 – derobert 2013-09-07 23:54:24

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;