我在使用CASE
的SQL语句中表达了一些奇怪的行为。它可以通过以下示例重现:
SELECT
CASE
WHEN 1=1
THEN 'foo'
WHEN 1=2
THEN (DATEADD(s, 1435586700, '01/01/1970 00:00:00'))
WHEN 1=3
THEN (DATEADD(s, 1435586700, '01/01/1970 00:00:00'))
ELSE
'bar'
END AS result
如果在SQL Server 2008上执行此操作,则不返回任何结果。只要您为第二个或第三个案例更改它成功,它就会返回一个值。如果您完全删除这些案例,它就可以正常工作。
起初我认为在任何情况下执行DATEADD
都会出现问题,并且因为传递参数值而失败。但在我的例子中,它们是不变的,无论如何都应该有用。
这里发生了什么?
答案 0 :(得分:6)
case
是一个表达式,其类型在编译时确定。但是,直到运行时才会实际评估这些值。
根据类型转换规则,我认为表达式将返回datetime
。当符合'foo'
条件时,这会导致'bar'
和when
值出错。
答案 1 :(得分:1)
各种选项中有不同的类型。这是完全错误的 - 案例表达式必须只有一种类型。
实际上,这可能会尝试将结果转换为datetime
。它无法将'foo'
转换为datetime
。
至于您关于dateadd
失败的说明,这不会是一个问题 - 实际上,case
是避免评估的几种方法之一所有选择。
案例表达方式有点脆弱;但是这应该已经发出警报 - 为什么你会考虑在同一列中返回两种不同的数据类型吗?这肯定会给你迟早带来麻烦(在这种情况下,更快;但它可能会在将来给你带来更多麻烦)。将两种不同的可能性分成两列(例如错误代码+日期时间等),或者将格式保留在应用程序上而不是将其填充到数据库中。
答案 2 :(得分:1)
试试这个...... 案例表达式应该是单一类型,所以我改变了单一类型的案例选项。
SELECT
CASE
WHEN 1=1
THEN 'foo'
WHEN 1=2
THEN CONVERT(VARCHAR(20),((dateadd(s, 1435586700, '01/01/1970 00:00:00'))))
WHEN 1=3
THEN CONVERT(VARCHAR(20),(dateadd(s, 1435586700, '01/01/1970 00:00:00'))
ELSE
'bar'
END AS result