sql-server - SQL Server 如何将日期与字符串文字进行比较?

标签 sql-server sql-server-2008 tsql datetime sql-server-2005

我正在修改查询,这是我的脚本:

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 如何匹配这样的日期。同样在日期格式中,我没有传递时间元素。

最佳答案

由于 data type precedence (since datetime has higher precedence than string types),SQL Server 将您传递的字符串文字 ('1/1/1900') 转换为日期时间值。如果您传递无效日期作为字符串,例如'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 并查找特定日期的值,则根本不应该使用相等性,而应该使用范围查询。例如,要查找 EndDate 为 2013 年 4 月 15 日的所有行(无论时间如何),您可以这样说:

WHERE EndDate >= '20130415'
  AND EndDate <  '20130416'

( Read this link to understand why you don't want to use BETWEEN here .)

如果您使用的是 SQL Server 2008 或更高版本,您仍然可以使用 CONVERT 在此列上实现可控制性,但这是一个罕见的异常(exception) - 通常您不想对某个列使用函数专栏。

WHERE CONVERT(DATE, EndDate) = '20130415'

其他一些评论 - 与您的问题不直接相关,但对您的代码进行了外围观察:

  1. Always use the schema prefix
  2. Never use SELECT * in production

关于sql-server - SQL Server 如何将日期与字符串文字进行比较?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16027045/

相关文章:

sql-server - STintersects() 找到交点

sql - 是否可以在 SQL Server 中使用 CLR 代码创建新的 T-SQL 运算符?

类似于 MySql REGEX 函数的 SQL Regex 函数

c# - 在 asp.net 中将字符串转换为 SQL Server uniqueidentifier

SQL,关于join的问题

sql-server - 如何使用 N 在 SQL Server 中插入多语言数据?

SQL Server 数据类型更改

sql - 在 SQL Server 2005 中设置和重置日期格式

sql-server - SQL Server 2008 - 如何从表值函数返回用户定义的表类型?

c# - 多维关系失去了与包装器的关系