在 SQL Server 中有多种拆分字符串的方法。本文涵盖了几乎所有方法的优点和缺点:
“SQL Server 2005 及更高版本中的数组和列表,当表值参数不适用时”,作者 Erland Sommarskog
您需要创建一个拆分功能。这是如何使用拆分功能的:
SELECT
*
FROM YourTable y
INNER JOIN dbo.yourSplitFunction(@Parameter) s ON y.ID=s.Value
我更喜欢在 TSQL 中拆分字符串的数字表方法,但是在 SQL Server 中拆分字符串的方法有很多,请参阅上一个链接,其中解释了每种方法的优点和缺点。
要使 Numbers Table 方法起作用,您需要执行此一次时间表设置,这将创建一个Numbers
包含 1 到 10,000 行的表:
SELECT TOP 10000 IDENTITY(int,1,1) AS Number
INTO Numbers
FROM sys.objects s1
CROSS JOIN sys.objects s2
ALTER TABLE Numbers ADD CONSTRAINT PK_Numbers PRIMARY KEY CLUSTERED (Number)
设置 Numbers 表后,创建此拆分函数:
CREATE FUNCTION [dbo].[FN_ListToTable]
(
@SplitOn char(1) --REQUIRED, the character to split the @List string on
,@List varchar(8000)--REQUIRED, the list to split apart
)
RETURNS TABLE
AS
RETURN
(
----------------
--SINGLE QUERY-- --this will not return empty rows
----------------
SELECT
ListValue
FROM (SELECT
LTRIM(RTRIM(SUBSTRING(List2, number+1, CHARINDEX(@SplitOn, List2, number+1)-number - 1))) AS ListValue
FROM (
SELECT @SplitOn + @List + @SplitOn AS List2
) AS dt
INNER JOIN Numbers n ON n.Number < LEN(dt.List2)
WHERE SUBSTRING(List2, number, 1) = @SplitOn
) dt2
WHERE ListValue IS NOT NULL AND ListValue!=''
);
GO
您现在可以轻松地将 CSV 字符串拆分为一个表并加入它或根据需要使用它,即使在动态 sql 中也是如此。以下是如何在您的问题的动态参数化查询中使用它:
DECLARE @Cmd as nvarchar(1000),@ParamDefinition nvarchar(1000);
Set @Cmd = N'SELECT * FROM table WHERE RegionCode in (SELECT ListValue FROM dbo.FN_ListToTable('','',@P1))'
SET @ParamDefinition = N'@P1 varchar(100)';
DECLARE @Code as nvarchar(1000);
SET @Code = 'X101,B202'
EXECUTE sp_executesql @Cmd, @ParamDefinition, @P1 = @Code
这是一个可以试用的工作示例(必须首先设置数字表和拆分功能):
CREATE TABLE YourTable (PK int primary key, RowValue varchar(5))
INSERT YourTable VALUES (1,'A')
INSERT YourTable VALUES (2,'BB')
INSERT YourTable VALUES (3,'CCC')
INSERT YourTable VALUES (4,'DDDD')
INSERT YourTable VALUES (5,'EEE')
INSERT YourTable VALUES (6,'FF')
INSERT YourTable VALUES (7,'G')
DECLARE @SQL nvarchar(1000)
,@ParamDefinition nvarchar(1000)
,@ParamValue varchar(100)
SELECT @SQL = N'SELECT * FROM YourTable WHERE PK IN (SELECT ListValue FROM dbo.FN_ListToTable('','',@P1))'
,@ParamDefinition = N'@P1 varchar(100)'
,@ParamValue = '2,4,,,6,,8,,2,,4'
EXECUTE sp_executesql @SQL, @ParamDefinition, @P1 = @ParamValue
输出:
PK RowValue
----------- --------
2 BB
4 DDDD
6 FF
(3 row(s) affected)