在存储过程中使用日期时间作为参数更新表时出错

Posted

技术标签:

【中文标题】在存储过程中使用日期时间作为参数更新表时出错【英文标题】:Error in Updating a table using datetime as parameter in Stored procedure 【发布时间】:2011-06-30 06:26:30 【问题描述】:

将 char 数据类型转换为 DateTime 数据类型导致 DateTime 值超出范围。 声明已终止。

ALTER PROCEDURE [dbo].[attendance_updatebyemployee_id]
@Employee_id int,
@AtDate datetime,
@FNLogged bit,
@ANLogged bit,
@LogTime varchar(10),
@LogOuttime varchar(10) 

AS
BEGIN   


    SET NOCOUNT ON;    
    update Mst_Attendance set FNLogged=@FNLogged,
    ANLogged=@ANLogged,LogTime=@LogTime,LogOuttime=@LogOuttime 
    where EmployeeId=@Employee_id and Atdate= @AtDate

END

在 C# 代码中,我将其命名为

 cmd.Parameters.AddWithValue("@AtDate",Dtime.ToString("dd/MMM/yyyy"));

在使用 SQl profiler 时,传递的数据是

exec [dbo].[attendance_updatebyemployee_id] @Employee_id=2,@AtDate='Feb 19 2011 12:00:00:000AM',@FNLogged=1,@ANLogged=0,@LogTime='11:45 AM',@LogOuttime=' ' 

在存储过程中,@AtDate 的值为 2011-02-19 00:00:00.000. 它正在破坏更新命令。

在表格内,日期保存为2/19/2011 12:00:00 AM

我该如何解决这个日期问题。

【问题讨论】:

能否请您发布代码或错误消息。这样我们就可以避免猜测的解决方案! 请贴出相关代码,会有帮助的。 至少你可以尝试从顶部将你的 char 转换为一个字符串并以这种方式传递它,或者如果你不想显示你的无论出于何种原因编码。 你问这个问题的方式并不聪明。您应该发布您收到的 exact 错误消息,以及您正在使用的确切代码的 sn-p,以便我们自己重现问题。在这一点上,您的问题几乎无法回答。出错的“可能”方式太多了。 您的 char 字符串很可能与默认的日期时间格式不匹配。尝试指定日期格式。 【参考方案1】:

从您的代码来看,您的 C# 代码中似乎有一个 DateTime 变量 - 所以只需按原样使用它 - 绝对不需要转换为字符串!!

如果你有:

ALTER PROCEDURE [dbo].[attendance_updatebyemployee_id]
  @Employee_id int,
  @AtDate datetime,
.....

那么你可以这样称呼它:

cmd.Parameters.AddWithValue("@AtDate", Dtime);

假设 Dtime 在 C# 中属于 DateTime 类型。

不要不必要地转换和投射东西!这只会引入潜在的破损和转换错误!只需按原样使用 DateTime - 它将被发送到 SQL Server 并在 T-SQL 中使用和识别为 DATETIME

如果您确实需要将日期值转换为字符串以将其传递给 SQL Server,我会始终建议使用 ISO-8601 标准格式:YYYYMMDDyyyy-MM-ddThh:mm:ss无论任何区域、语言或区域设置如何,它都能被识别和工作。

所以如果你绝对必须,那么使用:

Dtime.ToString("yyyyMMdd")

Dtime.ToString("yyyyMMddTHH:mm:ss")

仅此而已(所有其他格式都取决于语言和设置,可能在一种情况下有效,在另一种情况下可能会中断;ISO-8601 总是有效)

【讨论】:

更新 Mst_Attendance 设置 FNLogged=@FNLogged, ANLogged=@ANLogged,LogTime=@LogTime,LogOuttime=@LogOuttime where EmployeeId=@Employee_id and Atdate = FORMAT(@AtDate,'MM/DD/YYYY' ). 'FORMAT' 上的错误不是可识别的内置函数名称 @aswathi:请不要在评论中张贴代码之类的东西 - 几乎不可能阅读和理解。如果您需要提供更多信息,请通过编辑更新您的原始问题!【参考方案2】:

更新

你的格式化字符串应该是

ToString("MM\\/dd\\/yyyy hh:mm:ss tt")

这将在您的数据库中提供输出

02/19/2011 12:00:00 AM

您可以使用DateTime.TryParse() 将字符串转换为 DateTime 对象。

但是您需要确保该字符串实际上是日期时间表示。

示例(来自 MSDN)

string[] dateStrings = "05/01/2009 14:57:32.8", "2009-05-01 14:57:32.8", 
                        "2009-05-01T14:57:32.8375298-04:00", 
                        "5/01/2008 14:57:32.80 -07:00", 
                        "1 May 2008 2:57:32.8 PM", "16-05-2009 1:00:32 PM", 
                        "Fri, 15 May 2009 20:10:57 GMT" ;
DateTime dateValue;

Console.WriteLine("Attempting to parse strings using 0 culture.", 
                CultureInfo.CurrentCulture.Name);
foreach (string dateString in dateStrings)

if (DateTime.TryParse(dateString, out dateValue)) 
    Console.WriteLine("  Converted '0' to 1 (2).", dateString, 
                        dateValue, dateValue.Kind);
else
    Console.WriteLine("  Unable to parse '0'.", dateString);

// The example displays the following output:
//    Attempting to parse strings using en-US culture.
//       Converted '05/01/2009 14:57:32.8' to 5/1/2009 2:57:32 PM (Unspecified).
//       Converted '2009-05-01 14:57:32.8' to 5/1/2009 2:57:32 PM (Unspecified).
//       Converted '2009-05-01T14:57:32.8375298-04:00' to 5/1/2009 11:57:32 AM (Local).
//       Converted '5/01/2008 14:57:32.80 -07:00' to 5/1/2008 2:57:32 PM (Local).
//       Converted '1 May 2008 2:57:32.8 PM' to 5/1/2008 2:57:32 PM (Unspecified).
//       Unable to parse '16-05-2009 1:00:32 PM'.
//       Converted 'Fri, 15 May 2009 20:10:57 GMT' to 5/15/2009 1:10:57 PM (Local).

如果您知道要解析的日期格式是什么,那么您可以使用DateTime.TryParseExact() 并在第二个参数中指定您的格式:

DateTime.TryParseExact(dateString, "M/dd/yyyy hh:mm", enUS, 
                         DateTimeStyles.None, out dateValue)

【讨论】:

我认为问题不在于解析日期。我在调试存储过程时检查了所有格式。但在执行更新命令时显示相同的错误。 哦,它是用于 SQL 的,您之前没有提到过……您可以向我们展示您尝试解析的示例 DateTime 字符串【参考方案3】:

如果您有该工具,请使用SQL Profiler 实际查看传递给数据库的准确 SQL 字符串。这将帮助您找到错误。

【讨论】:

使用 SQl 分析器时。传递的数据是 exec [dbo]。[attendance_updatebyemployee_id] @Employee_id=2,@AtDate='Feb 19 2011 12:00:00:000AM',@FNLogged=1 ,@ANLogged=0,@LogTime='11:45 AM',@LogOuttime=' ' 将此添加到问题中,这将帮助您获得答案。为了获得更好的结果,还要显示客户端代码。看起来您对 DateTime 类型执行了 ToString() 或 ToShortDateTime() 。不要那样做。只需传递 DateTime,ADO 就会对其进行转换。 SQL Server 可能会在空格而不是斜杠上阻塞。 您将此标记为答案,请告诉我们(对此答案发表评论)您找到的答案,以便其他人获利。【参考方案4】:

只需在 3 个地方匹配数据类型:

C# 传递给存储过程的类型 您的存储过程所期望的类型 您的字段类型在数据库中

目前,

你的 C# 正在传递一个 stringDtime.ToString("dd/MMM/yyyy") 您的存储过程需要一个日期时间 (@AtDate datetime) 您在数据库中的 Atdate 字段似乎是 datetime (Atdate=@AtDate)

因此,要使它们都匹配,您只需调整 C# 代码,从字符串到 Dtime,如下所示:

cmd.Parameters.AddWithValue("@AtDate",Dtime);

我希望您数据库中的 Atdate 字段实际上是 DATETIME,而不是 VARCHAR。如果是 VARCHAR,则应保持 C# 代码不变,并更改存储过程中的 @AtDate 参数使其匹配:

@AtDate VARCHAR(10)

但如果可能的话,最好的办法是让它们都成为真正的 DATETIME。如果可以,请避免使用字符串(varchar)作为日期

【讨论】:

以上是关于在存储过程中使用日期时间作为参数更新表时出错的主要内容,如果未能解决你的问题,请参考以下文章

执行存储过程以删除表时出错

创建一个接受日期时间列表作为参数的存储过程

存储过程在从源视图更新表时存在性能问题

C#使用输出变量调用存储过程时出错,未提供参数

将Datetime作为参数传递给PyODBC的存储过程时出错

ORA-00904 使用 CASE 语句更新表时标识符无效