2009-05-06 48 views
2

從效率和最佳實踐的角度來看,我很欣賞每個人的想法。循環存儲過程或客戶端代碼

我有一個存儲過程,使(n)行的副本,並插入到必要的表中的行。

例如。製作庫存項目的副本並將副本添加到庫存。

我看到這種類型的存儲過程的兩個選項。

選項1:

CREATE PROCEDURE CopyInventory 
@InventoryID int 
AS 

BEGIN 

INSERT INTO Inventory (fieldOne, fieldTwo, FieldThree) 
(SELECT FieldOne, FieldTwo, FieldThree FROM Inventory WHERE InventoryID = @InventoryID) 

END 

使用選擇項一個我會多次調用存儲過程從在所述客戶端應用程序代碼while循環中。

選項2:使用

CREATE PROCEDURE CopyInventory 
    @InventoryID int, 
    @CopyCount int 
    AS 

    BEGIN 

    DECLARE @counter int 

    SET @counter = 0 

    WHILE @counter < @CopyCount 

    INSERT INTO Inventory (fieldOne, fieldTwo, FieldThree) 
    (SELECT FieldOne, FieldTwo, FieldThree FROM Inventory WHERE InventoryID = @InventoryID) 

    END 
END 

方案二我會從客戶端應用程序代碼一旦調用存儲過程,並通過在複印張數作爲參數。

選項二似乎是我的最佳選擇,因爲它只導致一次數據庫調用。

我很欣賞你的想法,爲什麼你會更喜歡一個而不是另一個或任何最佳實踐建議。

+1

當在sql land中時,認爲「基於集合」,在數據集上工作,只能循環作爲最後的手段。你需要有一個思路,我怎樣才能得到我需要的一組行,而不是像循環變量的程序那樣在循環中迭代。 – 2009-05-06 17:45:47

回答

8

當然在服務器端做。

這將爲您節省大量的客戶端和服務器之間的往返。如果你讓你的循環設置爲基礎

會更好:

WITH hier(cnt) AS 
     (
     SELECT 1 AS value 
     UNION ALL 
     SELECT cnt + 1 
     FROM hier 
     WHERE cnt < @count 
     ) 
INSERT 
INTO Inventory (fieldOne, fieldTwo, FieldThree) 
SELECT FieldOne, FieldTwo, FieldThree 
FROM hier, Inventory 
WHERE InventoryID = @InventoryID 
+0

而且邏輯全都在同一個地方 – Scoregraphic 2009-05-06 16:55:29

1

在這種情況下,我會說這樣做在服務器端。

通常情況下,我會說基於集合的操作應該在服務器端完成 - 因爲這是SQL Server特別擅長的,並且迭代操作應該在客戶端完成,因爲這是編譯語言擅長的。

1

如果這只是表現,那麼選項2是要走的路。

如果你能保持客戶端打開的連接脫身,然後有幾個原因採取選項1.

  1. 你可以很容易地把一個進度條在應用
  2. 你可以輕鬆地中止循環中的過程......就像用戶點擊取消一樣。
0

它確實需要分析,但我的第一個想法是,服務器端將是最好的。關鍵是運行循環的數據庫引擎的開銷是否大於重複發出命令的重複客戶端 - 服務器調用的開銷,並且這取決於數據庫會有所不同(我認爲有一個想法是,它可能適用於如果使用多個調用而不是單個存儲過程創建引擎,則可以爲存儲過程提供更好的併發性...純粹是一個實現細節)。

作爲一個建議,爲什麼不創建兩個?按照單一版本實現計數版本,然後您可以更輕鬆地對兩個選項進行並行分析,並查看哪些可以爲您的情況提供更好的性能。