Вам нужен способ разбить и обработать строку в TSQL, есть много способов сделать это. В этой статье рассматриваются плюсы и минусы практически каждого метода:
«Массивы и списки в SQL Server 2005 и более поздних версиях, когда параметры табличных значений не обрезают его» Эрланда Соммарского
Вам необходимо создать функцию разделения. Вот как можно использовать функцию разделения:
SELECT
*
FROM YourTable y
INNER JOIN dbo.yourSplitFunction(@Parameter) s ON y.ID=s.Value
Я предпочитаю подход с использованием таблиц чисел для разделения строки в TSQL , но существует множество способов разделения строк в SQL Server, см. Предыдущую ссылку, которая объясняет за и против каждого из них.
Чтобы метод таблицы чисел сработал, необходимо выполнить настройку единой таблицы, которая создаст таблицу Numbers
, содержащую строки от 1 до 10000:
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_ListToTableRows]
(
@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 return empty rows, and row numbers
----------------
SELECT
ROW_NUMBER() OVER(ORDER BY number) AS RowNumber
,LTRIM(RTRIM(SUBSTRING(ListValue, number+1, CHARINDEX(@SplitOn, ListValue, number+1)-number - 1))) AS ListValue
FROM (
SELECT @SplitOn + @List + @SplitOn AS ListValue
) AS InnerQuery
INNER JOIN Numbers n ON n.Number < LEN(InnerQuery.ListValue)
WHERE SUBSTRING(ListValue, number, 1) = @SplitOn
);
GO
проверить разбиение:
SELECT
RowNumber, CONVERT(datetime,ListValue) AS ListValue
FROM dbo.FN_ListToTableRows(',','1/1/2010 12:45am,,2/2/2010 1:23pm,3/3/2010 12:45')
ВЫВОД:
RowNumber ListValue
-------------------- -----------------------
1 2010-01-01 00:45:00.000
2 1900-01-01 00:00:00.000
3 2010-02-02 13:23:00.000
4 2010-03-03 12:45:00.000
(4 row(s) affected)
обратите внимание, что пропущенное значение во входной строке:
'1/1/2010 12:45am,,2/2/2010 1:23pm,3/3/2010 12:45'
^^
создал пустое строковое значение в наборе результатов функции, который CONVERT изменил на 1900-01-01 00: 00: 00.000, вы можете использовать оператор CASE для обработки их другим способом.
затем создайте свою функцию. Это основано на коде в вопросе. Я не уверен, что он делает, потому что он возвращает int
, который всегда равен нулю, и ничего не делает с запросом. Но это из функции OP, поэтому это должна быть простая форма того, что они делают:
CREATE FUNCTION [dbo].[GetData]
(
@StartTime varchar(8000), --CSV string of dates: '1/1/2010 12:45am,,2/2/2010 1:23pm,3/3/2010 12:45'
@EndTime varchar(8000) --CSV string of dates: '1/1/2010 12:45am,,2/2/2010 1:23pm,3/3/2010 12:45'
)
RETURNS int
AS
BEGIN
DECLARE @TempStates TABLE
(StartTime datetime NOT NULL
, EndTime datetime NOT NULL
, StateIdentity int NOT NULL
)
INSERT INTO @TempStates
SELECT s.StartTime
, s.EndTime
, s.StateIdentity
FROM State s
CROSS JOIN (SELECT
a1.RowNumber
,CONVERT(datetime,a1.ListValue) AS StartTime
,CASE
WHEN a2.ListValue > GETDATE() THEN GETDATE()
ELSE CONVERT(datetime,a2.ListValue)
END AS EndTime
FROM dbo.FN_ListToTableRows(',',@StartTime) a1
INNER JOIN dbo.FN_ListToTableRows(',',@EndTime) a2 ON a1.RowNumber=a2.RowNumber
) dt
WHERE s.StartTime <= dt.EndTime AND s.EndTime >= dt.StartTime
RETURN 0
END
GO