Vous avez besoin d'un moyen de diviser et de traiter la chaîne dans TSQL, il y a plusieurs façons de le faire. Cet article porte sur les avantages et les inconvénients de chaque méthode à peu près:
"Arrays and Lists in SQL Server 2005 and Beyond, When Table Value Parameters Do Not Cut it" by Erland Sommarskog
Vous devez créer une fonction split. Voici comment une fonction split peut être utilisé:
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 mais il existe de nombreuses façons de diviser les chaînes dans SQL Server, voir le lien précédent, ce qui explique les avantages et les inconvénients de chacun.
Pour la méthode de table de nombres au travail, vous devez faire une configuration de table de temps, ce qui va créer une table Numbers
qui contient des lignes de 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)
Une fois la table des numéros est mis en place , créer cette fonction split:
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
tester le fractionnement:
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')
SORTIE:
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)
Notez que la valeur manquante dans la chaîne d'entrée:
'1/1/2010 12:45am,,2/2/2010 1:23pm,3/3/2010 12:45'
^^
a créé une valeur de chaîne vide dans le jeu de résultats de la fonction, que le CONVERT a changé 1900-01-01 00: 00: 00.000, vous pouvez utiliser une instruction CASE pour les gérer d'une manière différente.
puis créez votre fonction. Ceci est basé sur le code int la question. Je ne suis pas sûr de ce qu'il fait, car il renvoie un int
, qui est toujours zéro, et ne fait rien avec la requête. Mais à partir de la fonction OPs, donc il doit être une forme simple de quelque chose qu'ils font:
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
Quelle est la question? – RedFilter