传递给存储过程的日期参数未按预期工作

本文关键字:工作 参数 日期 存储过程 | 更新日期: 2023-09-27 18:30:24

我在项目中遇到了一个问题,我将日期作为存储过程09/03/2013 23:59:59传递,但在探查器.net中看到将其转换为09/04/2013 00:00:00

为了确认我创建了一个小型测试应用程序(任何人都可以使用它进行复制,我使用的是.Net 4.5和Sql server 2012速成版)。

以下是测试代码:

DateTime startdate = DateTime.Parse("09/03/2013");
DateTime endDate = startdate.AddDays(1).AddTicks(-1);
        try
        {
            using (SqlConnection konekcija = new SqlConnection(ConfigurationManager.ConnectionStrings["default"].ToString()))
            {
                konekcija.Open();
                using (SqlCommand cmd = new SqlCommand())
                {
                    cmd.Connection = konekcija;
                    cmd.CommandType = CommandType.StoredProcedure;
                    cmd.CommandText = "[Interface].[uspTestDateParameter]";
                    cmd.Parameters.AddWithValue("@CurrentDate", startdate);
                    cmd.Parameters.AddWithValue("@BatchEndDate", endDate);
                    using (SqlDataAdapter da = new SqlDataAdapter(cmd))
                    {
                        // Fill the DataSet using default values for DataTable names, etc
                        DataSet dataset = new DataSet();
                        da.Fill(dataset);
                        DataTable dt = dataset.Tables[0];
                        //return dataset;
                    }
                }
            }
        }
        catch (Exception ee)
        {
        }

以下是程序:

CREATE PROCEDURE [Interface].[uspTestDateParameter]
(
@CurrentDate DateTime
,@BatchEndDate DateTime
) 
AS
BEGIN
Declare @table table (strt Datetime ,endT Datetime )
Insert into @table values (@CurrentDate,@BatchEndDate)
Select * from @table
END

返回的结果集9/3/2013 12:00:00 AM 9/4/2013 12:00:00 AM

我本可以附加数据集可视化工具的屏幕截图,但无法这样做,因为它需要声誉 10。 但以上是我得到的两列(strt,enDt)的值。

有人可以帮忙吗?由于这个原因,我的进程在生产中失败了。

传递给存储过程的日期参数未按预期工作

DATETIME四舍五入如下所述:

http://technet.microsoft.com/en-us/library/ms187819.aspx

本文明确指出,所有值都围绕 .000、.003 或 .007 秒。用户指定的日期时间01/01/98 23:59:59.999将始终存储为 1998-01-02 00:00:00.000

为什么不能执行以下操作,而不是使用即时报价?

DateTime endDate = startdate.AddDays(1).AddSeconds(-1);

实际上会通过你所说的通过日期(09/03/2013 23:59:59),而不是下一秒的刻度。

或者,使用 DATETIME2 作为您的 SQL 数据类型,根据文档,其精度为 100ns(一个刻度):

http://technet.microsoft.com/en-us/library/bb677335.aspx

问题在于 SQL Server datetime 类型的舍入,如 AntP 所述。

您可以考虑两种不同的解决方案:

选项 #1

在 SQL Server 中使用 datetime2 类型,正如 Tim 建议的那样。 它具有更高的精度,因此您不太可能四舍五入。 不过,这仍然很棘手,因为您必须知道要发送多少精度以及类型将支持多少精度。 换句话说,它应该23:59:59.999还是应该23:59:59.999999,或者23:59:59.0就足够了? 您必须决定什么对您的应用程序有意义。

如果数据始终包含整个日期,则可以将输入值更改为:

DateTime endDate = startdate.AddDays(1).AddSeconds(-1);

即使使用datetime类型,也不会四舍五入。

选项 #2

使用 [start,end) 的半开放间隔范围。 当结束日期是排除的时,您的查询要简单得多,您不必担心精度。 当两个间隔相互边界时,一个间隔的结束将与下一个间隔的开始完全相同。 永远不会有任何歧义,因为结束日期是排他性的。

不是将范围作为09/03/2013 00:00:00发送到09/03/2013 23:59:59,而是将其作为09/03/2013 00:00:00发送到09/04/2013 00:00:00,并了解不包括确切的结束日期。

换句话说,在

以下情况下,日期在某个范围内:

StartOfRange <= @TheDate < EndOfRange

或者换个说法:

StartOfRange <= @TheDate AND EndOfRange > @TheDate

在 .NET 方面,您仍然可以将输入词显示为完全包含的内容。 只需在将结束值传递到 SQL 之前适当地添加 a。 例如,如果您要求输入整个日期,则在结束日期中添加一整天。

Tick 是一个非常小的时间单位 (MSDN)。一毫秒内有 10,000 个刻度。

尝试减去 1-2 秒,看看它是否有效。

顺便说一句,SQL Server日期时间只能存储333毫秒(例如:.000,.003.,.006等)