【问题标题】:Formatted DateTime value is not getting inserted - sql未插入格式化的 DateTime 值 - sql
【发布时间】:2017-11-20 04:04:36
【问题描述】:

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

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) 但没有运气。我什至尝试用简单的DateTime.Now 替换loginTimeUtc.ToString("yyyy-mm-dd hh:mm:ss"),但效果不佳。知道我在这里可能做错了什么吗?

使用 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'

【问题讨论】:

  • 你的代码中loginTimeUtc的类型是什么?
  • @un-lucky 它是 DateTime 类型
  • 您可以将日期参数插入为 DateTime 类型。您不需要将其转换为字符串
  • 您正在从对象 C# System.DateTime 转换为 String,然后在您的更新中,您再次转换回 SQL DateTime,只需删除您的演员表,然后删除您的 ToString()
  • @JackyI 已删除 CAST AS DateTime 和 ToString("yyyy-mm-dd hh:mm:ss") 但仍然出现相同的错误

标签: c# .net sql-server datetime


【解决方案1】:

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

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

【讨论】:

  • 我仍然遇到“从字符串转换日期和/或时间时转换失败”错误
  • @sunsun 我会拿出 sql profiler 并检查实际正在执行的查询
  • 您尚未按照此答案中的说明进行实施,您在命令文本中的 LoginTimeUtc 参数周围仍有引号,它应为 .... N''99999999-9999-9999-9999-999999999999 '', @LoginTimeUtc, N''Low'')'...不是...N''99999999-9999-9999-9999-999999999999'', N''@LoginTimeUtc'', N''Low'' )'
  • @un-lucky 它现在对我有用。感谢您的帮助:) 欣赏它
  • @sunsun 你应该将他的答案标记为“答案”,即点击勾号
【解决方案2】:

我认为 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();
}

【讨论】:

  • 您的代码实际上是在尝试转换字符串“@LoginTimeUtc”:我不这么认为。它将获取应用程序端的日期并将其插入单引号之间。
  • @CodingYoshi 命令文本不受影响......它不会用字符串文字代替日期
【解决方案3】:

我看到你用loginTimeUtc.ToString("yyyy-mm-dd hh:mm:ss"),改成loginTimeUtc.ToString("yyyy-<b>MM-</b>dd hh:mm:ss")

请注意,MM 给你 2 位数的月份,而 mm 给你 2 位数的分钟。

要了解有关自定义 DateTime 格式的更多信息,请参阅here

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-10-07
    • 1970-01-01
    • 1970-01-01
    • 2012-06-06
    • 1970-01-01
    • 1970-01-01
    • 2015-06-07
    • 1970-01-01
    相关资源
    最近更新 更多