仅在View上从字符串转换日期和/或时间时,T-SQL转换失败

时间:2014-07-07 16:58:38

标签: sql sql-server

我尝试使用T-SQL查询来获取过去一周的数据。我有视图返回以下列:

Name (varchar) 
Date Registered (DateTime) 

我正在尝试使用该视图仅获取最后几周的数据。但是,我一直收到错误:

  

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

这是我的sql:

DECLARE @Now DATETIME = GETDATE();
DECLARE @6DaysAgo DATETIME = DATEADD(day,-6,@Now);

SELECT * 
FROM vw_Logs l
WHERE convert(DATETIME, 'l.Date Registered', 121) BETWEEN @6DaysAgo and @Now

当我编写完全相同的SQL语句时,使用表而不是视图,我不会收到错误。

DECLARE @Now DATETIME = GETDATE();
DECLARE @6DaysAgo DATETIME = DATEADD(day,-6,@Now);

SELECT * 
FROM tbl_Logs l
WHERE convert(DATETIME, l.DateRegistered, 121) BETWEEN @6DaysAgo and @Now

我怀疑它与列名有关?视图有一个空格(Date Registered),而表格没有(DateRegistered)。

是这样的吗?如果是这样,如何从视图中获取最后几周的数据,而无需更改列名?

2 个答案:

答案 0 :(得分:3)

完全相同的SQL语句!您需要在视图中用方括号括起您的列名称及其中的空格 - 而不是单引号:

SELECT * 
FROM vw_Logs l
WHERE CONVERT(DATETIME, l.[Date Registered], 121) BETWEEN @6DaysAgo AND @Now

将该表达式放在单引号中会使其成为字符串文字,并且字符串文字实际上不能很好地转换为DATETIME ....

答案 1 :(得分:1)

我在这里看到了几个问题。首先,为什么要将DateRegistered转换为日期时间?你声明它已经是一个日期时间列吗?进行比较时格式化它不会有任何区别。但它确实会使您的查询变为nonSARGable,并且现在忽略了该列的任何索引。

我看到的第二个问题是我猜你在过去6天内想要什么。你编码的方式不准确。您的计算将排除在当前时间之前的那一天发生的任何行。

查看变量的值。

DECLARE @Now DATETIME = GETDATE();
DECLARE @6DaysAgo DATETIME = DATEADD(day,-6,@Now);

select @Now, @6DaysAgo

相反,你可以做这样的事情。它是SARGable,它没有时间戳的问题。

SELECT [Column List]
FROM vw_Logs l 
WHERE l.[Date Registered] > dateadd(day, datediff(day, 0, getdate()) - 6, 0) 
and l.[Date Registered] < GETDATE()