17

我已经创建了一个具有这种结构的过程,但它不适用于datetime输入参数

我执行了这个查询但是

declare @a datetime
declare @b datetime 

set @a='2012/04/06 12:23:45'
set @b='2012/08/06 21:10:12'

exec LogProcedure 'AccountLog', N'test', @a, @b

但是 SQL Server 让我遇到了这个错误

从字符串转换日期和/或时间时转换失败。

但是当我用这个查询进行测试时,它可以工作

  exec LogProcedure 'AccountLog',N'test'

存储过程代码:

alter PROCEDURE LogProcedure
    @TableName VARCHAR(60),
    @SearchString NVARCHAR(50),
    @DateFirst DateTime = '',
    @DateLast DateTime = ''
AS
BEGIN
    SET NOCOUNT ON

    DECLARE @FinalSQL      NVARCHAR(MAX)

    SET @FINALSQL = 'SELECT * FROM [' + @TableName + '] where 1=2  '

    IF @DateFirst <> '' and @DateLast <> ''
       set @FinalSQL  = @FinalSQL + '  or convert (Date,DateLog) >=     '''+@DateFirst + ' and convert (Date,DateLog) <='''+@DateLast  

    SELECT 
       @FinalSQL  = @FinalSQL + ' or  [' + SYSCOLUMNS.NAME + '] LIKE N''%' + @SearchString + '%'' ' 
    FROM SYSCOLUMNS 
    WHERE OBJECT_NAME(id) = @TableName
    AND TYPE_NAME(SYSCOLUMNS.XTYPE) IN ('VARCHAR','NVARCHAR','CHAR','NCHAR','INT','DECIMAL')
    ORDER BY COLID

    EXEC(@FinalSQL)
END 

这个查询也是真的

SELECT * 
FROM AccountLog 
where 1=2  or convert (Date, DateLog) >= '2012/04/06' 
and convert (Date, DateLog) <='2012/08/06'
4

2 回答 2

35

您应该使用 ISO-8601 格式来表示日期的字符串 - 其他任何内容都取决于 SQL Server 语言和日期格式设置。

DATETIME仅使用日期时 的 ISO-8601 格式是:(YYYYMMDD没有破折号或反字符!)

对于DATETIME带有时间部分的 a,它是YYYY-MM-DDTHH:MM:SS(带有破折号,T中间是 a 以分隔日期和时间部分)。

如果要将字符串转换DATE为 SQL Server 2008 或更高版本的字符串,可以使用YYYY-MM-DD(带有破折号)来获得相同的结果。不要问我为什么这会如此不一致和令人困惑——它就是这样,你现在必须处理它。

所以在你的情况下,你应该尝试:

declare @a datetime
declare @b datetime 

set @a = '2012-04-06T12:23:45'   -- 6th of April, 2012
set @b = '2012-08-06T21:10:12'   -- 6th of August, 2012

exec LogProcedure 'AccountLog', N'test', @a, @b

此外 - 您的存储过程有问题,因为您将连接在一起datetime并将字符串连接成一个字符串,但您没有datetime先将其转换为字符串,而且您忘记了两个日期之后语句中的右引号。

因此,将此处的这一行更改为:

IF @DateFirst <> '' and @DateLast <> ''
   SET @FinalSQL  = @FinalSQL + '  OR CONVERT(Date, DateLog) >= ''' + 
                    CONVERT(VARCHAR(50), @DateFirst, 126) +   -- convert @DateFirst to string for concatenation!
                    ''' AND CONVERT(Date, DateLog) <=''' +  -- you need closing quotes after @DateFirst!
                    CONVERT(VARCHAR(50), @DateLast, 126) + ''''      -- convert @DateLast to string and also: closing tags after that missing!

使用这些设置,一旦你修复了包含问题的存储过程,它就会工作。

于 2012-04-08T09:21:57.237 回答
1

在你的 SP 的这一部分:

IF @DateFirst <> '' and @DateLast <> ''
   set @FinalSQL  = @FinalSQL
       + '  or convert (Date,DateLog) >=     ''' + @DateFirst
       + ' and convert (Date,DateLog) <=''' + @DateLast  

您正在尝试连接字符串和日期时间。

由于该datetime类型的优先级高于varchar/ nvarchar,因此该+运算符在字符串和日期时间之间发生时,将被解释为加法,而不是连接,然后引擎会尝试将您的字符串部分(' or convert (Date,DateLog) >= '''和其他部分)转换为日期时间或数值. 并且失败了。

如果在调用过程时省略最后两个参数,则不会发生这种情况,因为条件评估为 false 并且不执行有问题的语句。

要修改这种情况,您需要将日期时间变量显式转换为字符串:

set @FinalSQL  = @FinalSQL
    + '  or convert (Date,DateLog) >=     ''' + convert(date, @DateFirst)
    + ' and convert (Date,DateLog) <=''' + convert(date, @DateLast)

您还需要添加单引号:

set @FinalSQL  = @FinalSQL
    + '  or convert (Date,DateLog) >=     ''' + convert(date, @DateFirst) + ''''
    + ' and convert (Date,DateLog) <=''' + convert(date, @DateLast) + ''''
于 2012-04-08T09:28:10.343 回答