我有一个包含2个问题的存储过程。
它有40个参数。我知道第一个注释是重新设计我的存储过程,因此它没有40个参数。但是,这是一个具有较大标准部分的搜索表单。因此,用户为搜索指定了多达40个不同的标准。然后我们将这些值作为参数传递给每个人。现在我有一个40参数的sproc。将这些作为XML参数传递并将其解析为内部或表参数(我们仍在运行SQL 2k5但考虑升级到2k12)会更高效。
我的三个参数是由引号和逗号分隔的Guid值的长字符串。基本上,向用户呈现产品线列表,有时数百个。然后他们点击他们想要搜索的那些。我们限制了他们可以检查的行数,因为字符串太长了,但是我们传递了一长串由引号和逗号分隔的Guids。我知道这不是正确的方法。传递数组或Guid值集合的标准Trans SQl模式是什么?我有40个单独的字段,这样做。我们希望更有效地做到这一点,并且能够传递超过我们当前的限制。
答案 0 :(得分:4)
在您可以利用表值参数之前,我建议您创建一个专门的表值UDF来分割您的GUID参数。然后,您可以在join,exists子句,交叉应用等中使用输出
CREATE FUNCTION dbo.SplitGUIDs
(
@List VARCHAR(MAX),
@Delimiter VARCHAR(255)
)
RETURNS TABLE
WITH SCHEMABINDING
AS
RETURN
(
SELECT [GUID] = CONVERT(UNIQUEIDENTIFIER, x) FROM
(
SELECT x = RTRIM(y.i.value('.[1]', 'nvarchar(4000)'))
FROM
(
SELECT x = CONVERT(XML, '<i>'
+ REPLACE(@List, @Delimiter, '</i><i>')
+ '</i>').query('.')
) AS a CROSS APPLY x.nodes('i') AS y(i)
) AS x WHERE LEN(Item) > 0
);
GO
用法:
DECLARE @GUIDs VARCHAR(MAX);
SET @GUIDs = 'E2072E08-84D3-4EEA-A6ED-F38F1E4E34A6,'
+ 'A6B047BA-647E-4B35-8D95-F4A204B860F6';
SELECT [GUID] FROM dbo.SplitGUIDs(@GUIDs, ',') AS g;
结果:
Item
------------------------------------
E2072E08-84D3-4EEA-A6ED-F38F1E4E34A6
A6B047BA-647E-4B35-8D95-F4A204B860F6
存储过程可能如下所示:
CREATE PROCEDURE dbo.Whatever
@GUIDs VARCHAR(MAX)
AS
BEGIN
SET NOCOUNT ON;
SELECT t.columns
FROM dbo.sometable AS t
INNER JOIN dbo.SplitGUIDs(@GUIDs, ',') AS g
ON t.key = g.[GUID];
END
GO
(当然,如果字符串中的任何元素包含无效的GUID,该函数将失败。在SQL Server 2012中,您可以使用TRY_CONVERT()
但是您不需要因为您是使用TVP,更多信息如下。)
稍后当您从SQL Server 2005(以及面向此问题但在SQL Server 2008+上的其他读者)毕业时,您可以使用表类型更有效地执行此操作:
CREATE TYPE dbo.GUIDs AS TABLE(GUID UNIQUEIDENTIFIER PRIMARY KEY);
然后您的存储过程可以将此类型作为输入而不是大字符串:
CREATE PROCEDURE dbo.Whatever
@GUIDs dbo.GUIDs READONLY
AS
BEGIN
SET NOCOUNT ON;
SELECT t.columns
FROM dbo.sometable AS t
INNER JOIN @GUIDs AS g
ON t.key = g.[GUID];
END
GO
(注意切换到TVP是多么容易 - 只需更改第2行和第9行。)
然后,您的Web应用程序可以将诸如DataTable之类的集合传递给@GUIDs参数。没有杂乱的字符串拆分,没有类型转换,没有人为限制你可以传递多少个不同的GUID。
答案 1 :(得分:0)
听起来像是你试图通过一个存储过程实现太多。 我会尝试打破搜索算法或查询较小的peices并将特定搜索实体的特定结果整理到结果集中。
可能的替代方案:
在T-SQL中必须解析CSV(手动)是我个人认为在大多数情况下代码/架构气味。
编辑:只需阅读...... http://technet.microsoft.com/en-US/library/ms187926(v=sql.90).aspx
存储过程最多可包含2,100个参数。
那么问题是什么?我以为你出于某种原因会遇到限制。 只需使用更多参数,它就无限优于解析CSV。 另外请不要忘记,您可以为存储的proc参数提供默认值,这样您每次调用时都不必提供所有40多个参数,前提是它们是以命名方式发送的。
另外请不要忘记表值UDF ......它们非常好用,因为它们可以以下面的方式使用
select * from dbo.fn_ProductsByLine('Toasters') pbl inner join dbo.fn_ProductsByPrice(10,20) pbp on pbl.productID = pbp.productID