您需要一种方法来分割和处理TSQL中的字符串,有很多方法可以做到这一点。本文介绍了几乎每一个方法的优点和缺点:
"Arrays and Lists in SQL Server 2005 and Beyond, When Table Value Parameters Do Not Cut it" by Erland Sommarskog
你需要创建一个分裂的功能。这是一个分裂的功能如何使用:
SELECT
*
FROM YourTable y
INNER JOIN dbo.yourSplitFunction(@Parameter) s ON y.ID=s.Value
I prefer the number table approach to split a string in TSQL但也有许多方法来拆分在SQL Server中的字符串,见前面的链接,这说明各的优点和缺点。
对于数字表的方法来工作,你需要做的这一次表的设置,这将创建一个包含从1到10000行的表Numbers
:
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')
OUTPUT:
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
问题是什么? – RedFilter 2010-04-14 16:04:09