【问题标题】:Loop in stored procedure or in client code在存储过程或客户端代码中循环
【发布时间】:2009-05-06 16:48:41
【问题描述】:

从效率和最佳实践的角度来看,我很欣赏大家的想法。

我有一个存储过程,它制作 (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

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

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

感谢您对为什么更喜欢其中一个或两者都不喜欢的想法以及任何最佳实践建议。

【问题讨论】:

  • 在 sql 领域中,考虑“基于集合”,处理数据集,仅循环作为最后的手段。你需要有这样的心态:我如何才能得到我需要的一组行,而不是像程序循环变量那样在循环中迭代。

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


【解决方案1】:

当然是在服务器端做。

这将为您节省大量客户端和服务器之间的往返。

如果你让你的循环基于集合会更好:

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

【讨论】:

  • 而且逻辑都在同一个地方
  • @KM:不,这不是拼写错误,而是故意的。 CNT 在 CTO 声明中声明,这就是您可以在查询中使用任何别名的原因。我更喜欢在当前级别查询中使用其他名称来区分当前级别列和PRIOR级别列。
  • @Quassnoi,当我尝试它时,我一直收到错误,直到我将它从“AS Value”更改为“AS cnt”。但是,当我再次尝试时,它可以正常工作。感谢您清除它
【解决方案2】:

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

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

【讨论】:

    【解决方案3】:

    如果您只是追求性能,那么选项 2 就是要走的路。

    如果您可以避免保持客户端上的连接打开,那么选择选项 1 有几个原因。

    1. 您可以轻松地在应用程序中放置进度条
    2. 您可以在循环中间轻松中止进程...就像用户单击取消一样。

    【讨论】:

      【解决方案4】:

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

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-02-10
        • 1970-01-01
        • 1970-01-01
        • 2012-11-29
        • 2011-12-25
        • 1970-01-01
        • 2015-01-19
        • 1970-01-01
        相关资源
        最近更新 更多