4

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

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

下面是测试代码:

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)的值。

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

4

3 回答 3

4

DATETIME按此处所述四舍五入:

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

本文明确指出所有值都在 0.000、0.003 或 0.007 秒左右。用户指定的 DateTime01/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

于 2013-09-06T18:17:59.977 回答
1

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

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

选项1

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

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

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

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

选项 #2

使用 的半开区间范围[start,end)。当结束日期是唯一的时,您的查询会更简单,您不必担心精确度。当两个区间彼此相邻时,一个区间的结束将与下一个区间的开始完全相同。永远不会有任何歧义,因为结束日期是唯一的。

不是发送范围 as 09/03/2013 00:00:00to 09/03/2013 23:59:59,而是发送它09/03/2013 00:00:0009/04/2013 00:00:00理解确切的结束日期不包括在内。

换句话说,日期在一个范围内,如果:

StartOfRange <= @TheDate < EndOfRange

或者换一种说法:

StartOfRange <= @TheDate AND EndOfRange > @TheDate

在 .NET 方面,您仍然可以将输入术语呈现为完全包容性。只需在将其传递给 SQL 之前将适当的值添加到结束值。例如,如果您要求输入整个日期,则将一整天添加到结束日期。

于 2013-09-06T18:29:24.953 回答
0

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

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

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

于 2013-09-06T18:22:44.367 回答