存储过程中的多值日期参数?

我正在尝试使用一个存储过程来接受日期的多值参数。 这不是在SSRS中,但我试图使用与它相同的方法:

ALTER PROCEDURE spSelectPlacementData ( @ClientID SMALLINT, @SourceFileDates VARCHAR(MAX) ) AS BEGIN SELECT (snip) FROM [APS].[dbo].[Account] A WHERE ClientID = @ClientID AND A.[SourceFileDate] IN (SELECT * FROM dbo.Split(@SourceFileDates)) END 

我在SSRS报告多值参数上使用此方法和INT和VARCHAR字段。

这是我用来连接SourceFileDates的代码:

  string sourceFileDates = ""; foreach (DateTime file in job.sourceFiles) { if (file == job.sourceFiles.Last()) { sourceFileDates += "'" + file.ToString("d") + "'"; } else { sourceFileDates += "'" + file.ToString("d") + "', "; } } selectRunCommand = new SqlCommand("spSelectPlacementData", sqlConnection); selectRunCommand.CommandType = CommandType.StoredProcedure; selectRunCommand.Parameters.Add("@ClientID", SqlDbType.SmallInt); selectRunCommand.Parameters["@ClientID"].Value = job.clientID; selectRunCommand.Parameters.Add("@SourceFileDates", SqlDbType.VarChar); selectRunCommand.Parameters["@SourceFileDates"].Value = sourceFileDates; 

使用这个dbo.Splitfunction我在网上抓了:

 /****** Object: UserDefinedFunction [dbo].[Split] Script Date: 09/20/2011 11:16:13 ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO ALTER FUNCTION [dbo].[Split] /* This function is used to split up multi-value parameters */ ( @ItemList VARCHAR(MAX), @delimiter CHAR(1) ) RETURNS @IDTable TABLE (Item VARCHAR(MAX) collate database_default ) AS BEGIN DECLARE @tempItemList VARCHAR(MAX) SET @tempItemList = @ItemList DECLARE @i INT DECLARE @Item VARCHAR(MAX) SET @tempItemList = REPLACE (@tempItemList, @delimiter + ' ', @delimiter) SET @i = CHARINDEX(@delimiter, @tempItemList) WHILE (LEN(@tempItemList) > 0) BEGIN IF @i = 0 SET @Item = @tempItemList ELSE SET @Item = LEFT(@tempItemList, @i - 1) INSERT INTO @IDTable(Item) VALUES(@Item) IF @i = 0 SET @tempItemList = '' ELSE SET @tempItemList = RIGHT(@tempItemList, LEN(@tempItemList) - @i) SET @i = CHARINDEX(@delimiter, @tempItemList) END RETURN END 

我想我不完全清楚我如何格式化参数,SSRS如何对类似参数这样做(这是我尝试从代码中做的唯一一个),以及Date数据类型如何影响所需格式。 我收到了“从字符串转换日期和/或时间时转换失败”。 选择多个值时出错。

编辑:根据要求,foreach循环输出的示例:

‘9/9/2011’,’8/19/2011’,’8/12/2011’

为什么不使用Table-Valued参数 ?

在SQL上创建用户定义的表类型DateTimes

 create type DateTimes as table ( [Value] datetime ) 

然后修改您的存储过程:

 ALTER PROCEDURE spSelectPlacementData ( @ClientID SMALLINT, @SourceFileDates DateTimes readonly -- must be readonly ) 

现在,您可以将@SourceFileDates视为只读表变量。

指定SqlCommand参数时,Table-Valued参数指定为SqlDbType.Structured并作为DataTableDataRowcollection 。 所以,你可以像这样填充它:

 var sourceFileDates = new DataTable(); sourceFileDates.Columns.Add("Value", typeof(DateTime)); foreach (DateTime file in job.sourceFiles) { sourceFileDates.Rows.Add(file); } selectRunCommand.Parameters.Add(new SqlParameter { ParameterName = "@SourceFileDates", Value = sourceFileDates, SqlDbType = SqlDbType.Structured // make sure you specify structured }); 

现在一切都很好并且输入正确…而且您不必进行任何字符串解析或转换。

作为旁注,您也可以继续创建StringsIntegers类型; 你会迷上TVP并在整个地方使用它们。

SSRS有点欺骗,因为它控制着输入…它并不是那么关心SQL注入攻击。 通过存储过程,这将更难做到。

当我需要在2005年在一个参数中发送多个值时,对我来说效果很好,我会将它们作为XML字符串发送,如下所示:

  2011-01-23 2011-02-24  

然后将其视为函数中的表:

 select xavalue('.', 'datetime') as myDate from @XMLArg.nodes('/dates/date') x(a); 

现在你应该把你的数据作为表值。 (语法可能有点偏,这不是我的头脑)