Lar*_*ady 0 sql t-sql sql-server sql-server-2005 query-optimization
我有一个有两个问题的存储过程。
它有 40 个参数。我知道第一条评论是重新设计我的存储过程,使其没有 40 个参数。然而,这是一个带有大标准部分的搜索表单。因此,用户最多可以指定 40 个不同的搜索条件。然后我们将这些值作为参数传递。现在我有一个 40 个参数的存储过程。将它们作为 XML 参数传递并在内部或表参数中解析它是否会更有效(我们仍在运行 SQL 2k5,但正在考虑升级到 2k12)。
我的三个参数是由引号和逗号分隔的 Guid 值的长字符串。基本上,用户会看到一个产品线列表,有时有数百个。然后他们单击想要搜索的内容。我们限制了他们可以检查的行数,只是因为字符串太长,但我们传递了一长串由引号和逗号分隔的 Guid。我知道这不是正确的方法。用于传递像这样的 Guid 值的数组或集合的标准 Trans SQl 模式是什么?40 个领域中,我有 3 个独立领域在做这件事。我们希望更有效地做到这一点,并且能够传递超出当前限制的内容。
在您可以利用表值参数之前,我建议您创建一个专门的表值 UDF 来拆分 GUID 参数。然后,您可以在连接、存在子句、交叉应用等中使用输出。
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(x) > 0
);
GO
Run Code Online (Sandbox Code Playgroud)
用法:
DECLARE @GUIDs VARCHAR(MAX);
SET @GUIDs = 'E2072E08-84D3-4EEA-A6ED-F38F1E4E34A6,'
+ 'A6B047BA-647E-4B35-8D95-F4A204B860F6';
SELECT [GUID] FROM dbo.SplitGUIDs(@GUIDs, ',') AS g;
Run Code Online (Sandbox Code Playgroud)
结果:
Item
------------------------------------
E2072E08-84D3-4EEA-A6ED-F38F1E4E34A6
A6B047BA-647E-4B35-8D95-F4A204B860F6
Run Code Online (Sandbox Code Playgroud)
存储过程可能如下所示:
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
Run Code Online (Sandbox Code Playgroud)
(当然,如果字符串中的任何元素包含无效的 GUID,该函数将会失败。在 SQL Server 2012 中,您可以使用该函数,TRY_CONVERT()但之后就不需要这样做了,因为您将使用 TVP,更多内容见下文。)
稍后,当您从 SQL Server 2005 毕业时(以及对于其他面临此问题但使用 SQL Server 2008+ 的读者),您可以使用表类型更有效地完成此操作:
CREATE TYPE dbo.GUIDs AS TABLE(GUID UNIQUEIDENTIFIER PRIMARY KEY);
Run Code Online (Sandbox Code Playgroud)
然后您的存储过程可以将此类型作为输入而不是大字符串:
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
Run Code Online (Sandbox Code Playgroud)
(注意切换到 TVP 是多么容易 - 只需要更改第 2 行和第 9 行。)
然后,您的 Web 应用程序可以将 DataTable 等集合传递给 @GUIDs 参数。没有混乱的字符串分割,没有类型转换,没有对可以传递的不同 GUID 数量的人为限制。