循环存储过程或客户端代码

时间:2009-05-06 16:48:41

标签: .net sql-server tsql stored-procedures

从效率和最佳实践的角度来看,我欣赏每个人的想法。

我有一个存储过程,它会生成(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

使用选项2,我将从客户端应用程序代码调用存储过程一次,并将副本计数作为参数传递。

选项二似乎是我的最佳选择,因为它只会导致一次数据库调用。

我很感激您对为什么您更喜欢一个或两个以及任何最佳实践建议的想法。

4 个答案:

答案 0 :(得分: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

答案 1 :(得分:1)

在这种情况下,我会说在服务器端这样做。

通常,我会说基于集合的操作应该在服务器端完成 - 因为这是SQL Server特别擅长的,并且迭代操作应该在客户端完成,因为这是编译语言擅长的。

答案 2 :(得分:1)

如果只是你想要的表现,那么选择2就是你要走的路。

如果你可以让客户端上的Connection保持打开状态,那么选择1就有几个原因。

  1. 您可以轻松地在应用程序中添加进度条
  2. 您可以轻松地在循环中间中止该过程...就像用户点击取消一样。

答案 3 :(得分:0)

它真的需要分析,但我首先想到的是服务器端是最好的。关键是运行循环的数据库引擎的开销是否大于重复发出命令的重复客户端 - 服务器调用的开销,这将取决于数据库(我认为有一种可能是如果存储过程是通过多个调用而不是单个存储过程来为存储过程提供更好的并发性的引擎......纯粹是一个实现细节。

作为一个建议,为什么不创造两者?根据单个版本实施计数版本,然后您可以更轻松地并排分析这两个选项,并查看哪种选项可以为您的情况提供更好的性能。