我正在修改查询,这是我的脚本:
select
CASE When EndDate='1/1/1900'
THEN NULL
ELSE EndDate END,*
from Members
此脚本只是比较日期,如果是'1/1/1900'则返回null
,否则返回日期。
我可以在我的数据库中看到日期存储的格式如下:
1900-01-01 00:00:00.000
问题是当我的模式与存储模式不同时,SQL Server如何匹配日期。同样在日期格式中,我没有传递时间元素。
答案 0 :(得分:18)
SQL Server将您传递的字符串文字('1/1/1900'
)转换为data type precedence (since datetime has higher precedence than string types)的日期时间值。如果您将无效日期作为字符串传递,例如'2/31/1900'
,您将收到转换错误(Msg 242
),因为SQL Server并不知道2月31日的含义。它并不是试图匹配一个看起来像你传递的字符串,它将两者都转换为日期的内部表示(更多关于我的评论)。
在专门处理日期时,不要再考虑格式了,除了当你传递字符串文字时,m/d/y
(或者是d/m/y
?)是一种可怕的格式使用。更安全使用:
YYYYMMDD
您的查询应为:
SELECT CASE When EndDate = '19000101'
THEN NULL ELSE EndDate END, ...other columns...
FROM dbo.Members;
这样,当您通过9月8日这样的日期时,它不会被SQL Server,其他读者等错误解释。09/08/2013
9月8日或8月9日?取决于你所在的世界的哪个部分,对吗?在你的情况下它是可以的,因为日期和月份是相同的,但事实并非如此。请参阅以下文章:
(请,请完整阅读该链接。)
最后,如果您正在使用DATETIME/SMALLDATETIME
并且正在查找特定日期的值,则不应该使用相等,而是使用范围查询。例如,要查找2013年4月15日EndDate
落在的所有行,无论何时,您都会说:
WHERE EndDate >= '20130415'
AND EndDate < '20130416'
(Read this link to understand why you don't want to use BETWEEN
here。)
如果您使用的是SQL Server 2008或更高版本,您仍然可以使用CONVERT
在此列上实现sargability,但这是一个罕见的例外 - 通常您不希望对列使用函数
WHERE CONVERT(DATE, EndDate) = '20130415'
其他一些评论 - 与您的问题没有直接关系,但是有关您的代码的外围观察: