我在一些SQL服务器查询中遇到了问题。 原来我有一个表,其中包含“属性名称”和“属性值”字段,可以是任何类型,并存储为varchar。(是的...我知道。)
所有特定属性的日期似乎都存储在“YYYY-MM-DD hh:mm:ss”格式中(不确定百分之百,因为这里有数百万条记录),因此我可以毫无问题地执行以下代码:
select /*...*/ CONVERT(DATETIME, pa.Attribute_Value)
from
ProductAttributes pa
inner join Attributes a on a.Attribute_ID = pa.Attribute_ID
where
a.Attribute_Name = 'SomeDate'
然而,如果我执行以下代码:
select /*...*/ CONVERT(DATETIME, pa.Attribute_Value)
from
ProductAttributes pa
inner join Attributes a on a.Attribute_ID = pa.Attribute_ID
where
a.Attribute_Name = 'SomeDate'
and CONVERT(DATETIME, pa.Attribute_Value) < GETDATE()
我将得到以下错误:从字符串转换日期和/或时间失败。
为什么它在where子句上失败而不是在select子句上?
另一个线索:
如果我使用存储在数据库中的实际Attribute_ID(PK)而不是通过Attribute_Name进行过滤,则可以正常工作,没有问题。
select /*...*/ CONVERT(DATETIME, pa.Attribute_Value)
from
ProductAttributes pa
inner join Attributes a on a.Attribute_ID = pa.Attribute_ID
where
a.Attribute_ID = 15
and CONVERT(DATETIME, pa.Attribute_Value) < GETDATE()
更新
感谢大家的回答。我发现很难选择一个正确的答案,因为每个人都指出了对理解问题有用的东西。它肯定与执行顺序有关。
事实证明,我的第一个查询工作正常,因为WHERE子句先执行,然后是SELECT。
我的第二个查询失败是由于同样的原因(因为属性没有被过滤,所以在执行相同的WHERE子句时转换失败)。
我的第三个查询有效,因为ID是索引的一部分(PK),所以它优先处理并首先根据该条件钻取结果。
谢谢!
WHERE
子句中谓词的顺序。这并不是有保障的。当你在一个列中混合使用数据类型时,唯一安全的处理方式是使用CASE
表达式。 - Martin SmithAttribute_Value
包含非日期,你正在将该列转换为日期。你必须相信某种形式的预过滤是有保证的。 - Martin Smith