将首选项类型参数传递给存储过程 - 最佳实践?

时间:2013-10-07 16:03:47

标签: sql-server-2008 stored-procedures sql-server-2008-r2 sql-server-2012

我需要提供一个解决方案,将多个参数传递给SQL Server 2008中的一系列报告存储过程。参数将是用户首选项,可能包含用户选择多个类型的列表价值(例如多个月)。可能有多达30个不同的参数,其中60%可能包含多个选项。

到目前为止,我有3个选项。

  1. 使用set接口将值作为普通参数传递 - 这似乎很快失败,因为我需要传递集合(多个月就是一个很好的例子)。

  2. 将参数作为单个XML片段传递。这个方法已经在这里使用了,虽然我不确定它是否可以处理相同类型的多个元素(例如上面几个月)。代码使用DynaFilter来解析XML - 我从来没有听说过它,也无法在互联网上找到任何参考。编写代码的开发人员明天回来,所以我会有更多的信息。

  3. 使用表值参数 - 我只是刚刚开始研究它们,但它们看起来很有前景,似乎提供了良好的性能。

  4. 我们正在使用带有ASP.Net MVC前端的SQL Server 2008。如果需要,我们可以搬到2012年。

    我已经开始并将继续对处理这个问题的最佳方法进行更多的研究,但是如果有任何其他选择,我会重视对最佳前进方向的任何意见。

    提前致谢。

1 个答案:

答案 0 :(得分:0)

以下是使用表值参数执行此操作的方法。这些是在SQL 2008中引入的,因此如果您选择这条路线,那么该版本对您的解决方案来说会很好。在这个测试场景中,我正在创建一个主表和一个相关的表,其中一个外键指向主键。

首先,创建表数据类型:

CREATE TYPE primary_tbltype AS TABLE 
   (personkey int NOT NULL PRIMARY KEY,
    firstname varchar(30),
    lastname varchar(30))

CREATE TYPE related_tbltype AS TABLE 
   (fk_personkey int NOT NULL,
    accountnum varchar(30),
    accountbalance money)

创建存储过程:

CREATE PROCEDURE MySproc
    @PrimaryTable primary_tbltype READONLY,
    @RelatedTable related_tbltype READONLY
AS
BEGIN
DECLARE @CurrentKey INT
DECLARE @FirstName VARCHAR(30)
DECLARE @LastName VARCHAR(30)
DECLARE @AccountTotal MONEY

DECLARE PersonCursor CURSOR LOCAL FAST_FORWARD FOR
    SELECT personkey, firstname, lastname FROM @PrimaryTable
OPEN PersonCursor
FETCH NEXT FROM PersonCursor INTO @CurrentKey, @FirstName, @LastName
WHILE @@FETCH_STATUS= 0 BEGIN

    SELECT @AccountTotal = SUM(accountbalance) FROM @RelatedTable 
        WHERE fk_personkey = @CurrentKey

    PRINT @FirstName + ' ' + @LastName + ' - account total: ' + CONVERT(VARCHAR(30), @AccountTotal)

    FETCH NEXT FROM PersonCursor INTO @CurrentKey, @FirstName, @LastName
END
END;

这里有一些测试数据可供试用:

DECLARE @primaryTVP primary_tbltype
DECLARE @relatedTVP related_tbltype

INSERT INTO @primaryTVP values (1, 'John', 'Cleese')
INSERT INTO @primaryTVP values (2, 'Eric', 'Idle')
INSERT INTO @primaryTVP values (3, 'Graham', 'Chapman')

INSERT INTO @relatedTVP values (1, '29310918', 28934.33)
INSERT INTO @relatedTVP values (2, '123123', 3418.11)
INSERT INTO @relatedTVP values (2, '33333', 666.66)
INSERT INTO @relatedTVP values (3, '554433', 22.22)
INSERT INTO @relatedTVP values (3, '239482', 151515.15)


EXEC MySproc @primaryTVP, @relatedTVP;

使用TVP的一些优势涵盖here,并且它们也能够参与基于集合的操作。