尽量简短。这是我在SQL Server 2008 R2数据库中的表和SP:
CREATE TABLE dbo.TEST_TABLE
(
ID INT NOT NULL IDENTITY (1,1) PRIMARY KEY,
VALUE varchar(23)
)
GO
CREATE PROCEDURE USP_TEST_PROCEDURE
(
@Param1 varchar(23)
)
AS
BEGIN
INSERT INTO TEST_TABLE (VALUE) VALUES (@Param1)
END
GO
这是C#代码:
using (SqlConnection con = GetConection())
{
using (var cmd = new SqlCommand("USP_TEST_PROCEDURE", con))
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add("@Param1", SqlDbType.DateTime, 23).Value = "2013-12-10 12:34:56.789";
cmd.Connection.Open();
cmd.ExecuteNonQuery();
}
}
注意我故意将@ Param1的类型指定为DateTime。 现在启动SQL Server Profiler并运行.NET代码。完成后,不要停止探查器,只需查看输出。我看到RPC的以下文本:Completed EventClass:
exec USP_TEST_PROCEDURE @Param1='2013-12-10 12:34:56.790'
现在复制此文本,打开SSMS,粘贴到新查询窗口并运行而不做任何更改。现在停止探查器并确保SSMS在探查器中生成与ADO.NET应用程序相同的文本:
exec USP_TEST_PROCEDURE @Param1='2013-12-10 12:34:56.790'
现在从TEST_TABLE表中选择。我看到以下结果:
ID VALUE 1 Dec 10 2013 12:34PM 2 2013-12-10 12:34:56.790
问题是为什么两个相同的命令(从SQL Server Profiler的角度来看)产生不同的结果?
似乎探查器无法正确显示场景背后的情况。运行.NET应用程序后,我希望看到以下内容:
DECLARE @Param1 Datetime = '2013-12-10 12:34:56.789';
exec USP_TEST_PROCEDURE @Param1=@Param1
在这种情况下,我很清楚为什么我有790毫秒而不是789.这是因为日期时间类型不是很精确。它四舍五入到.000,.003或.007秒的增量。见:datetime (Transact-SQL)我也很清楚为什么我有'2013年12月10日下午12:34'而不是'2013-12-10 12:34:56.790'。这是因为当datetime转换为字符串时,默认使用'mon dd yyyy hh:miAM(或PM)'格式。请参阅CAST and CONVERT (Transact-SQL)以下示例演示了:
DECLARE @Param1 Datetime = '2013-12-10 12:34:56.789';
DECLARE @Param1_varchar varchar(23);
SELECT @Param1 --2013-12-10 12:34:56.790
SET @Param1_varchar = @Param1;
SELECT @Param1_varchar; --Dec 10 2013 12:34PM
GO
如果我的理解是正确的,那么我想重新解释一下这个问题:为什么SQL Server Profiler会显示一些奇怪而令人困惑的东西?有没有更正的选择?
答案 0 :(得分:0)
您的应用程序正在发送日期时间,但由于您选择了varchar列,因此会在进入时隐式转换。就像print中所发生的那样:
DECLARE @d DATETIME = GETDATE();
SELECT @d; -- this is still a datetime
PRINT @d; -- this is implicitly converted to a string
如果您不喜欢这种令人困惑的行为,请停止混合数据类型。绝对没有理由将日期时间值存储在varchar列中。