【问题标题】:getting error while converting to date time in stored procedure在存储过程中转换为日期时间时出错
【发布时间】:2018-09-30 18:03:58
【问题描述】:

我收到如下错误:

消息 241,级别 16,状态 1,过程 spQueryMgt,第 106 行 [批处理 Start Line 13] 转换日期和/或时间时转换失败 来自字符串。

ALTER PROCEDURE [dbo].[spQueryMgt]
    @Mode               varchar(50)='',
    @Query_Form         varchar(20)='',
    @Patient_ID         bigint=0,
    @Verified_By        bigint = 0,
    @Verified_Date      datetime=''
AS
BEGIN
IF(@mode='Post_Query')
BEGIN

DECLARE @sql NVARCHAR(MAX);

SET @sql = N'Update '+ CONVERT(varchar(12), @Query_Form) +' Set
        Verified_By='+CONVERT(VARCHAR(12), @Verified_By)+',
        Verified_Date='''+CONVERT(datetime, @Verified_Date,20)+'''
        where Patient_ID = '+CONVERT(varchar(12), @Patient_ID)

        EXEC sp_executeSQL @sql;

END
END

【问题讨论】:

  • 你能在EXEC sp_exe...上方的过程中添加PRINT @sql吗?
  • 尝试从@Verified_Date 中删除convert。注射也要小心
  • Verified_Date='+CONVERT(datetime, @Verified_Date,20)+' 此更改可能有效。
  • 作为旁注,最好用 null 而不是 '' 来初始化 datetime 参数
  • 您可能想查看example 如何以更安全的方式执行动态 sql。因为SQL injection 不好。

标签: sql sql-server sql-server-2008


【解决方案1】:

将您的查询更改为 -

SET @sql = N'Update '+ CONVERT(varchar(12), @Query_Form) +' Set
        Verified_By='+CONVERT(VARCHAR(12), @Verified_By)+',
        Verified_Date='''+CONVERT(VARCHAR(20), @Verified_Date,20)+'''
        where Patient_ID = '+CONVERT(varchar(12), @Patient_ID)

您的 convert 函数存在问题。您正在将@Verified_Date 转换为datetime 并将datetime 连接到varchar 字符串。

【讨论】:

  • 但是值是日期时间。
  • 是的,您是正确的,即值是日期时间,但我们不能将日期时间值与 varchar 字符串连接。
  • @DhruviParikh 这不是使用sp_executeSQL 过程的正确方法。请研究它,也正如@uzi 所提到的,您的程序允许 SQL 注入。
【解决方案2】:

问题是您将日期时间转换回日期时间,然后尝试连接,这给了您该异常。

而且,通过将参数初始化为 '' 和 0,您正在使用不必要的值填充数据库,例如 '' 用于 varchars,1900-01-01 用于日期时间列,更糟糕的是整数列中的 0。
那是你真正想要的吗?我对此表示怀疑。
无法确定某个字段是故意设置为该值还是留空并在以后给您带来麻烦。

你可以像这样在空参数中获取 NULL 值

ALTER PROCEDURE [dbo].[spQueryMgt] (
  @Mode               varchar(50) = NULL,
  @Query_Form         varchar(20) = NULL,
  @Patient_ID         bigint = NULL,
  @Verified_By        bigint = NULL,
  @Verified_Date      datetime = NULL
)
AS
BEGIN
  SET NOCOUNT ON; 

  IF @mode ='Post_Query'
  BEGIN
     DECLARE @sql NVARCHAR(MAX);

     if (@Query_Form is not null) and (@Patient_ID is not null) -- nu use in updating when no table or id is given
     begin
         SET @sql = N' Update ' + CONVERT(varchar(12), @Query_Form) +
                     ' Set Verified_By = ' + isnull(CONVERT(VARCHAR(12), @Verified_By), 'null') + ',' +
                     ' Verified_Date = ' + case when @Verified_Date is null then 'null' else '''' + CONVERT(varchar(20), @Verified_Date, 20) + '''' end + 
                     ' where Patient_ID = ' + isnull(CONVERT(varchar(12), @Patient_ID), 'null')

         EXEC sp_executeSQL @sql;
     end
  END
END

编辑
正如 cmets 中提到的,您还应该注意 sql 注入,这使您的过程更安全,但也更容易

create PROCEDURE [dbo].[spQueryMgt] (
  @Mode               varchar(50) = NULL,
  @Query_Form         varchar(20) = NULL,
  @Patient_ID         bigint = NULL,
  @Verified_By        bigint = NULL,
  @Verified_Date      datetime = NULL
)
AS
BEGIN
  SET NOCOUNT ON 

  IF @mode = 'Post_Query'
  BEGIN
     DECLARE @sql NVARCHAR(MAX)

     if (@Query_Form is not null) and (@Patient_ID is not null) -- nu use in updating when no table or id is given
     begin
         SET @sql = N'Update @P0 ' + 
                     'set Verified_By = @P1, ' + 
                     '    Verified_Date = @P2 ' + 
                     'where Patient_ID = @P3'

         EXEC sp_executesql @sql, 
              N'@P0 varchar(20), @P1 bigint, @P2 bigint, @P3 datetime', 
              N'@P0 = @Query_Form, @P1 = @Verified_By, @P2 = @Verified_Date, @P3 = @Patient_ID'
     end
  END
END

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-09-07
    • 1970-01-01
    • 2014-06-18
    • 1970-01-01
    • 2016-09-16
    • 2013-08-29
    • 2023-03-29
    • 1970-01-01
    相关资源
    最近更新 更多