格式化的DateTime值未插入 - sql

时间:2017-11-20 04:04:37

标签: c# .net sql-server datetime

我正在尝试从我的代码执行此查询

using (SqlCommand usageMapCmd = new SqlCommand())
{
    usageMapCmd.Connection = sqlConnection;
    usageMapCmd.CommandType = CommandType.Text;
    usageMapCmd.CommandText = "INSERT [dbo].[Analytics_DeviceLog] ([IPAddress], [OS], [OSVersionMajor], [OSVersionMinor], [City], [Country], [CountryCode], [Region], [RegionCode], [PostalCode], [TimeZone], [Browser], [BrowserVersionMajor], [BrowserVersionMinor], [Device], [Model], [Platform], [Latitude], [Longitude], [Languages], [UserGuid], [LoginTimeUtc], [LocationAccuracy]) VALUES (N'119.15.106.186', N'Windows 10', NULL, NULL, N'Canberra', N'Australia', N'AU', N'Australian Capital Territory', N'ACT', N'2600', N'Australia/Sydney', N'@Browser', 60, CAST(0.00 AS Decimal(18, 2)), N'@Device', N'', N'WinNT', CAST(-35.305000 AS Decimal(9, 6)), CAST(149.141200 AS Decimal(9, 6)), N'en-US,en;q=0.8,vi;q=0.6', N'99999999-9999-9999-9999-999999999999', CAST(N'@LoginTimeUtc' AS DateTime), N'Low')";
    usageMapCmd.Parameters.AddWithValue("@Browser", (string)browsers[rndBrowsers.Next(browsers.Count)]);
    usageMapCmd.Parameters.AddWithValue("@Device", (string)devices[rndDevices.Next(devices.Count)]);
    usageMapCmd.Parameters.AddWithValue("@LoginTimeUtc", loginTimeUtc.ToString("yyyy-mm-dd hh:mm:ss"));
    usageMapCmd.ExecuteNonQuery();
}

我遇到的问题是无论我输入的@LoginTimeUtc格式是什么,我都会收到错误

  

从字符串

转换日期和/或时间时转换失败

奇怪的是当我从SQL Server Management Studio手动执行查询时,例如2017-08-21 05:45:52.830这样可以正常工作,所以我认为问题不是来自我的数据库。

我试过了。 DateTime.Parse(loginTimeUtc)但没有运气。我甚至试图用简单的loginTimeUtc.ToString("yyyy-mm-dd hh:mm:ss")替换DateTime.Now,但它不能正常工作。知道我在这里做错了什么吗?

使用SQL Server Profiler,这就是我得到的:

exec sp_executesql N'INSERT [dbo].[Analytics_DeviceLog] ([IPAddress], [OS], [OSVersionMajor], [OSVersionMinor], [City], [Country], [CountryCode], [Region], [RegionCode], [PostalCode], [TimeZone], [Browser], [BrowserVersionMajor], [BrowserVersionMinor], [Device], [Model], [Platform], [Latitude], [Longitude], [Languages], [UserGuid], [LoginTimeUtc], [LocationAccuracy]) VALUES (N''119.15.106.186'', N''Windows 10'', NULL, NULL, N''Canberra'', N''Australia'', N''AU'', N''Australian Capital Territory'', N''ACT'', N''2600'', N''Australia/Sydney'', N''@Browser'', 60, CAST(0.00 AS Decimal(18, 2)), N''@Device'', N'''', N''WinNT'', CAST(-35.305000 AS Decimal(9, 6)), CAST(149.141200 AS Decimal(9, 6)), N''en-US,en;q=0.8,vi;q=0.6'', N''99999999-9999-9999-9999-999999999999'', N''@LoginTimeUtc'', N''Low'')',N'@Browser nvarchar(6),@Device nvarchar(17),@LoginTimeUtc datetime',@Browser=N'Chrome',@Device=N'Samsung Galaxy S4',@LoginTimeUtc='2009-02-19 21:56:00'

3 个答案:

答案 0 :(得分:2)

而不是将DateTime转换为格式化字符串,而是将它们转换为数据库和存储的DateTime,您可以通过指定Parameters.Add使用SqlDbType直接传递DateTime对象:

 usageMapCmd.CommandText = "INSERT [dbo].[Analytics_DeviceLog] ([LoginTimeUtc]) VALUES (@LoginTimeUtc)";
 usageMapCmd.Parameters.Add("@LoginTimeUtc",SqlDbType.DateTime).value = loginTimeUtc;

答案 1 :(得分:0)

我认为Un-Lucky的答案是正确的解决方案,但您可以通过将命令文本更改为...来获得代码。

usageMapCmd.CommandText = "INSERT [dbo].[Analytics_DeviceLog] ([IPAddress], [OS], [OSVersionMajor], [OSVersionMinor], [City], [Country], [CountryCode], [Region], [RegionCode], [PostalCode], [TimeZone], [Browser], [BrowserVersionMajor], [BrowserVersionMinor], [Device], [Model], [Platform], [Latitude], [Longitude], [Languages], [UserGuid], [LoginTimeUtc], [LocationAccuracy]) VALUES (N'119.15.106.186', N'Windows 10', NULL, NULL, N'Canberra', N'Australia', N'AU', N'Australian Capital Territory', N'ACT', N'2600', N'Australia/Sydney', N'@Browser', 60, CAST(0.00 AS Decimal(18, 2)), N'@Device', N'', N'WinNT', CAST(-35.305000 AS Decimal(9, 6)), CAST(149.141200 AS Decimal(9, 6)), N'en-US,en;q=0.8,vi;q=0.6', N'99999999-9999-9999-9999-999999999999', CAST(@LoginTimeUtc AS DateTime), N'Low')";

即。改变

CAST(N'@LoginTimeUtc' AS DateTime) 

CAST(@LoginTimeUtc AS DateTime),

您的代码实际上是在尝试转换字符串“@LoginTimeUtc”而不是您传递的参数

编辑:确定在创建一个说服CodingYoshi的示例时,我发现上面代码的另一个问题是使用的日期格式化程序应该是“yyyy-MM-dd hh:mm:ss”不是“yyyy-mm-dd hh:mm:ss”。无论如何,我已经测试了以下内容......

using (SqlCommand cmd = new SqlCommand())
{
    cmd.Connection = new SqlConnection("Data Source=(local);Initial Catalog=mytstDB;Integrated Security=True;pooling=true;Min Pool Size=5; Max Pool Size=10");
    cmd.Connection.Open();
    cmd.CommandText = "SELECT * FROM tblUser WHERE CreatedDate <= CAST(N'@LoginTimeUtc' AS DateTime)";
    cmd.Parameters.AddWithValue("@LoginTimeUtc", DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss"));
    SqlDataReader rdr = cmd.ExecuteReader();
    rdr.Read();
}

在Profiler中生成以下SQL

exec sp_executesql N'SELECT * FROM tblUser WHERE CreatedDate <= CAST(N''@LoginTimeUtc'' AS DateTime)',N'@LoginTimeUtc nvarchar(19)',@LoginTimeUtc=N'2017-11-20 04:46:39'

失败并出现与上述类似的错误。虽然,以下sql工作..

exec sp_executesql N'SELECT * FROM tblUser WHERE CreatedDate <= CAST(@LoginTimeUtc AS DateTime)',N'@LoginTimeUtc nvarchar(19)',@LoginTimeUtc=N'2017-11-20 04:46:39'

通过将上述代码更改为......可以复制哪些内容。

using (SqlCommand cmd = new SqlCommand())
{
    cmd.Connection = new SqlConnection("Data Source=(local);Initial Catalog=29150930_sonic_dev_next;Integrated Security=True;pooling=true;Min Pool Size=5; Max Pool Size=10");
    cmd.Connection.Open();
    cmd.CommandText = "SELECT * FROM tblUser WHERE CreatedDate <= CAST(@LoginTimeUtc AS DateTime)";
    cmd.Parameters.AddWithValue("@LoginTimeUtc", DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss"));
    SqlDataReader rdr = cmd.ExecuteReader();
    rdr.Read();
}

答案 2 :(得分:0)

我看到您使用loginTimeUtc.ToString("yyyy-mm-dd hh:mm:ss"),将其更改为loginTimeUtc.ToString("yyyy-MM-dd hh:mm:ss")

注意MM给你2个月的数字,而mm给你2个数字的分钟。

要阅读有关自定义日期时间格式的更多信息,请参阅here