当前位置: 首页 > 面试题库 >

仅在WHERE子句上转换为datetime失败?

欧阳勇军
2023-03-14
问题内容

我对某些SQL Server查询有问题。原来,我有一个带有“ Attibute_Name”和“
Attibute_Value”字段的表,该表可以是任何类型,存储在varchar中。(是的,我知道。)

特定属性的所有日期似乎都以“ YYYY-MM-DD hh:mm:ss”格式存储(对此不确定100%,此处有数百万条记录),因此我可以毫无问题地执行此代码

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_Name进行过滤,而是使用存储在数据库(PK)中的实际Attribute_ID,它将毫无问题地工作。

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子句中进行的,则可以比在投影列表中显示的记录(值)进行更多的记录(值)评估。我之前在不同的上下文中已经讨论过这一点,请参见T-SQL函数并不暗示一定的执行顺序,并且在SQL
Server上布尔运算符短路
。您的情况甚至更简单,但相似,并且最终的根本原因是相同的:在处理诸如SQL之类的声明性语言时,不要假设命令执行顺序。

最好的解决方案是清理数据并将列类型更改为DATETIME或DATETIME2类型。 所有 其他变通办法都会有一个缺点或另一个缺点,因此您最好做正确的事。

更新

经过仔细研究(对不起,我是@VLDB,并且只是在会话之间偷看SO),我意识到您拥有一个具有固有的无类型语义(attribute_value可以是bea字符串,日期,int等)的EAV存储。我的观点是,最好的选择是sql_variant在存储中使用,直到客户(例如project
sql_variant)。您可以在客户端中使类型一致,所有客户端API都有从中提取内部类型的方法sql_variant,请参见使用sql_variant数据(以及,几乎所有客户端API
…在CLR中使用sql_variant数据类型)。通过使用sql_variant您可以存储多种类型而无需经历字符串表示形式的问题,您可以使用它SQL_VARIANT_PROPERTY来检查诸如BaseType 在存储的值中,甚至可以像检查约束一样思考以强制数据类型正确性。



 类似资料:
  • 在oracle数据库上似乎有很多查询语法来获取数据,这里我只想问一下运行良好的查询,但我完全不明白。查询如下: 从上面的查询来看,它的工作很好。但是我不明白为什么会有TO_DATE('01/01/197000:00:00','mm/dd/yyyy hh24:mi:ss和(create_date/(60*60*24)),'mm/dd/yy hh24:mi:ss') 有人能解释一下吗? 提前致谢

  • 问题内容: 如何转换字符串字段并用于Where子句。 衬板是varchar2 例外:无效的数字 问题答案: 仅在数字时比较 或简单:

  • 问题内容: 我有这个查询: 但是我想做这样的事情: 如何检查电子邮件是否存在?我要使用电子邮件,如果此字段为空,我要使用email2。我该如何完成? 问题答案: 用于选择字段,然后在其后放置该子句:

  • 问题内容: 我有一个WebService返回DateTime字段。 我得到一个结果,但是 我想我怎么能做到这一点。 通过设置Header Content-Type:application / json; charset = utf-8; 我得到了类似的结果。 问题答案: 您可以更改您的WS以返回带有DateTime值的long。要返回的值是自Unix纪元(01/01/1970)以来的毫秒数。这可以

  • 本章提供了有关如何使用JDBC应用程序从表中选择记录的示例。 这将在从表中选择记录时使用WHERE子句添加其他条件。 在执行以下示例之前,请确保您具备以下示例 - 要执行以下示例,您可以使用实际用户名和密码替换用户名和密码。 您的MySQL或您正在使用的任何数据库已启动并正在运行。 所需的步骤 (Required Steps) 使用JDBC应用程序创建新数据库需要以下步骤 - Import the

  • 使用Query DSL和hibernate(Spring Data JPA)构建查询,如下所示 这里的逻辑很简单:如果有一个与某个人关联的银行帐户,则按银行ID过滤结果。 实体具有一个,它包含整数值。实体可能具有也可能没有