Есть много способов разбить строку в SQL Server.В этой статье рассматриваются преимущества и недостатки практически каждого метода:
«Массивы и списки в SQL Server 2005 и более поздних версиях, когда параметры табличных значений не сокращаются», Эрланд Соммарског
Вам необходимо создать функцию разделения.Вот как можно использовать функцию разделения:
SELECT
*
FROM YourTable y
INNER JOIN dbo.yourSplitFunction(@Parameter) s ON y.ID=s.Value
Я предпочитаю подход с таблицей чисел для разделения строки в TSQL , но в SQL Server существует множество способов разделения строк, см.предыдущая ссылка, которая объясняет за и против каждого из них.
Чтобы метод таблицы чисел работал, вам нужно выполнить эту настройку таблицы времени, которая создаст таблицу 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)
После настройки таблицы чисел создайте эту функцию разделения:
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)