【问题标题】:SQL Server 2005 - Are there any major negative implications to returning multiple tables w/ stored procedures?SQL Server 2005 - 返回带有/存储过程的多个表是否有任何重大负面影响?
【发布时间】:2009-08-10 01:50:47
【问题描述】:

在过去的几个月中,我遇到了多种情况,其中旧版 sql SP 返回一个主要由冗余信息组成的表。

例子:

从...中选择 CustomerID、CustomerEmail、CustomerAddress、InventoryLineItem、ShipQty

返回:

55 a@b.com 723 StreetName InvLineItem#1 45
55 a@b.com 723 StreetName InvLineItem#2 42
55 a@b.com 723 StreetName InvLineItem#3 1
55 a@b.com 723 StreetName InvLineItem#4 5
55 a@b.com 723 StreetName InvLineItem#5 200
55 a@b.com 723 StreetName InvLineItem#6 7045

(前 3 个字段永远不会改变)

由于我是该项目的唯一开发人员,因此我开始将其分解为两个选择语句。 (我也在处理接收 .NET 代码)

从...中选择 CustomerID、CustomerEmail、CustomerAddress。

Returns: 55 a@b.com 723 Streetname  <-- 1 record

从 ...中选择 InventoryLineItem、ShipQty 返回:

LineItem#1 45
LineItem#2 42
LineItem#3 1

等等

显然,.NET 中生成的数据集更小,但有时在选择语句中总是有 10 个字段在所有情况下都完全相同,这确实让我感到烦恼。一些查询甚至可能返回数十万条记录。

我觉得我在这里做的事情是正确的,但我又不是 SQL 专家。

我有什么理由避免这种做法吗?

提前感谢您的宝贵时间。

【问题讨论】:

    标签: sql sql-server sql-server-2005 sql-server-2008


    【解决方案1】:

    如果您的客户端使用从存储过程返回的数据可以正确处理多个结果集,那么不,绝对没有理由不使用它们。

    正如您已经指出的那样,它们有几个优点:
    - 减少传输的数据量 - 保持规范化,没有不必要的数据重复 - 与必须调用两个单独的存储过程(一个用于标头,一个用于详细数据)相比,可以节省到服务器的往返时间

    总而言之 - 去吧! :-) 对我来说似乎是个好主意。

    马克

    【讨论】:

      【解决方案2】:

      好吧,我的重要答案是,如果您要将输出提供给 SSRS 等报告框架,那么多个表格会让您的生活变得困难——报告框架非常擅长获取非规范化的结果并将其处理成漂亮的报告。

      就性能而言,不,您没有理由避免存储过程中出现多个结果集。只要您在客户端使用 DataReader 和 .NextResult() ,IMO 你就是金子。

      【讨论】:

        【解决方案3】:

        我一直使用多个结果集。

        在您的情况下,我将有 2 个,一个用于标题,一个用于详细信息。 通常,客户端无论如何都必须提取标头:当客户端不能那样使用它时,我为什么要扁平化它(例如膨胀它)?

        我使用它的另一个领域是网页。对数据库的每次调用对于屏幕上的一个操作或弹出窗口来说都是足够的数据(假设现在没有缓存)。

        比如说,一个标题行,5 个详细信息行 + 用于详细信息行下拉列表的查找行。

        另一个原因是性能。 SQL 查询可以调整,C# 代码可以调整,但往返(例如 web 数据库)不能。

        【讨论】:

          【解决方案4】:

          我认为您对冗余数据的看法是正确的。
          它是流经网络的额外数据。

          您可能正在使用与您正在选择的相同参数之一调用存储过程。

          例如GetCustomerOrders 'ALFKI' - 可能会返回

          阿尔夫基 |阿尔法客户 | OID001 ......
          阿尔夫基 |阿尔法客户 | OID002 ......
          阿尔夫基 |阿尔法客户 | OID003……

          因此,您可以避免选择作为参数传递给存储过程的字段。

          编辑:再想一想,可能还有另一个存储过程——它将返回客户相关信息。发票相关过程将返回给定客户 ID 的发票数据。

          【讨论】:

          • 在返回集中包含您传递的参数意味着应用程序在提交查询和取回数据之间忘记了这些值。
          【解决方案5】:

          我发现存储过程返回的内容的一致性可能非常重要,但您肯定会看到不具有一致性的系统存储过程(考虑 sp_help)。

          所以这真的取决于你追求什么,以及你的客户端代码是否能够处理它。任何时候你想要提前绑定,或者你有一个客户端会询问存储过程它将返回什么(例如任何报告客户端,或诸如 LINQ 之类的 ORM 系统),那么你可能会遇到麻烦。如果您使用的是 .Net 代码,并且希望每次都看到不同的结果集结构,那么这可能没什么大不了的。

          归根结底,如果您有大量列在某些情况下可能是空的,这可能会为您的客户提供更大的灵活性,但这完全取决于您要将工作放在哪里。

          我个人的偏好是拥有一个形状始终相同的单一结果集。但话又说回来,我也会考虑将其放入表值函数中,以便我可以以更灵活的方式处理结果(例如分组等)。我发现存储过程非常适合当客户需要调用某些东西时,但是如果我想以不同的方式处理东西,我宁愿有一个视图或一个表值函数来生成它(很像从系统移动Microsoft 不久前关闭的 DMV 的存储过程)。

          罗伯

          【讨论】:

            【解决方案6】:

            这样做我最大的担心是,如果您的数据库是高度事务性的,那么两个查询之间的数据可能无法正确关联。换句话说,第二个查询可能包含不在第一个查询中的记录(因为它们是在第一个查询完成时添加的),因此您不知道它们的相关数据。这当然也可以反过来工作,即第一个查询的记录在第二个查询运行之前被删除。

            【讨论】:

            • 这是可以(并且应该)处理事务隔离的东西; SP 通常由多个语句组成,因此这种一致性参数并不真正取决于返回的是一个还是多个记录集。
            【解决方案7】:

            听起来这不适用于您的情况,但是如果存储过程被另一个存储过程调用,则在第一个存储过程之后返回的任何数据集都将是“不可见的”——即不可访问——由调用程序。使执行 INSERT... EXECUTE... 语句变得困难。 (当然,这些集合将返回给调用应用程序。)

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 2011-04-06
              • 2014-05-22
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多