【问题标题】:Converting "dd/MM/yy hh:mm tt" String To DateTime "yyyy-mm-dd hh:mm:ss.000" And Passing It As SQL Parameter将 "dd/MM/yy hh:mm tt" 字符串转换为 DateTime "yyyy-mm-dd hh:mm:ss.000" 并将其作为 SQL 参数传递
【发布时间】:2015-11-16 18:11:17
【问题描述】:

我一直在为 DateTimes 和 SQL Server 苦苦挣扎。

即使我已经测试了转换并确认它有效。

string date = "21/12/15 11:45 AM";
DateTime TempDate = DateTime.ParseExact(date, "dd/MM/yy hh:mm tt", CultureInfo.InvariantCulture);
Console.WriteLine(TempDate);
//Returns 2015.12.21. 11:45:00

当我将相同的逻辑应用于 SQL 时,它会显示以下错误:

System.ArgumentException:无法转换为 System.Int32。
参数名称:type ---> System.FormatException:输入字符串格式不正确。

当我使用以下代码时

Command.Parameters.Add("@DateNext", SqlDbType.DateTime);
Command.Parameters["@DateNext"].Value = DateTime.ParseExact(SurDateNext, "dd/MM/yy hh:mm tt", CultureInfo.InvariantCulture);
//Where SurDateNext is the following string "21/12/15 11:45 AM"

我尝试插入值的字段是 DateTime,默认格式为 yyyy-mm-dd hh:mm:ss.000

我到底做错了什么?

【问题讨论】:

  • 出于好奇,如果你执行 DateTime tempDate = DateTime.ParseExact(...) 然后设置参数 Value = tempDate 你会得到什么?
  • 什么是“类型”参数?
  • 没有名为“type”的参数,我猜它只出现在错误消息中,可能是SqlDbType。
  • 您可以发布您的存储过程代码示例吗?看起来参数被定义为错误的类型,所以 SQL 试图隐式转换它并且不能。
  • 您确定您的 SQL 期望的是日期时间而不是整数值吗?

标签: c# sql-server date datetime


【解决方案1】:

正在运行的查询:
更新日期 SET DateNow=CAST('2015-12-21 11:45:00' AS DATETIME) WHERE ID='135'

错误是抱怨一个整数,而不是日期。我的猜测是,直到过程的后期您才会看到异常,它实际上是在抱怨 ID 值,它似乎包含不应该包含单引号的值。

您希望代码结构更像这样:

string sql = "UPDATE [Dates] SET DateNow= @DateNext WHERE ID= @ID ;";

如果您曾经看到原始数据值被替换到该查询中,那您就做错了错误!使用查询参数的全部意义在于参数data从不包含在sql命令中,这样就不存在向命令中注入恶意数据的可能。

此外,您根本不必担心发送到 Sql Server 的日期时间值的格式。将日期字符串放入 .Net DateTime 变量中,使用带有 DateTime 参数的参数化查询,并将数据保存在 Sql Server DateTime 列中。让 ADO.Net 处理其余部分。

您似乎认为 Sql Server 使用yyy-mm-dd hh:mm:ss.000 格式存储您的日期,但这并不准确。 Sql Server 使用二进制(不可读)格式存储日期。为方便起见,只是您的数据库/查询工具向您显示其他格式。

让我们把整个事情放在一起:

string SurDateNext = "21/12/15 11:45 AM";
string sql = "UPDATE [Dates] SET DateNow= @DateNext WHERE ID= @ID ;";
using (var cn = new SqlConnection("connection string here"))
using (var cmd = new SqlCommand(sql, cn))
{
    cmd.Parameters.Add("@DateNext", SqlDbType.DateTime).Value = DateTime.ParseExact(SurDateNext, "dd/MM/yy hh:mm tt", CultureInfo.InvariantCulture);
    cmd.Parameters.Add("@ID", SqlDbType.Int).Value = 135;

    cn.Open();
    cmd.ExecuteNonQuery();
}

给定一个有效的连接字符串和表定义,我向您保证该代码将起作用。

如果您有 任何 附加值包含在该查询中并且不使用查询参数,那么让我们先解决这个问题。然后确保DateTime.ParseExact()Convert.ToInt32() 和类似代码都出现在它们自己的行中,这样您就可以单步执行代码并找到导致错误的确切行以及值是什么。

【讨论】:

  • 非常感谢您的努力和解释,这将有很大帮助!现在我终于知道我做错了什么。
  • 那是什么? :)
【解决方案2】:

我将冒险回答这个问题,因为我相当确定我知道问题的根源。

海报表明正在使用内联 SQL(参数化)。这也适用于存储过程。发帖人还表示,他/她的 SQL 中没有名为“type”的参数。这表明问题嵌套在 SQL 语句中,并且在尝试调用内部或用户定义的 SQL 函数时产生错误。示例:

UPDATE Employee SET EditedOn = CAST(@SomeDate as datetime)

如果不能将 @SomeDate 转换为有效的日期时间,则 CAST 函数本身可能会出错。以下是一些有助于解决问题的观察:

  • 如果您不使用某种 ORM,请使用存储过程。学习如何使用它只需要最少的时间,而且前期的微小投资可以收回大约 1000 倍,因为...
  • 如您所见,内联 SQL 使调试变得更加困难。当遇到任何类型的 SQL 错误且解决方案不明显时,我建议的第一件事是通过 SQL Management Studio 手动执行存储过程,绕过 C#。这将立即告诉您问题是您的 C# 代码还是您的 T-SQL。
  • 尽可能使用正确的数据类型。不要将日期存储为 nvarchar,或者在 SQL 参数应该是日期时间时接受它作为 nvarchar。这不仅使代码本质上不安全并且容易出现错误,而且当您开始处理越来越大的数据集时,对 SQL 数据执行函数可能是索引查找和表扫描之间的区别,因此(在严重的情况下) ),一个以毫秒而不是几小时执行的存储过程。如果一个字段应该存储一个日期时间,那么就让它成为一个日期时间。在您拥有其架构的数据库中,应非常谨慎地使用 CAST 和 CONVERT。
  • 最后,您可以(并且应该)使用 SQL 分析器开始跟踪您的数据库。然后您可以看到正在执行的 EXACT 查询。您可以将查询直接从 Profiler 复制/粘贴到 SQL Server Management Studio 中,使用它直到您可以正常工作,然后修复您的 C# 代码。

【讨论】:

  • 我也有过这样的想法,但最终“无法转换为 System.Int32”是 .Net 错误,而不是 Sql Server 错误。他的问题甚至在他打开数据库连接之前就出现了。
  • @JoelCoehoorn 很好的观察。我想知道 SurDateNext 在他的第二个代码块中的值是什么。
  • 这是一个字符串。 “21/12/15 上午 11:45”
  • 您能否提供一个可以执行以复制您的问题的最低限度完整的代码块?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-01-26
  • 2019-01-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多