我遇到了一些SQL服务器查询的问题.事实证明我有一个带有"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'
Run Code Online (Sandbox Code Playgroud)
但是,如果我执行以下代码:
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()
Run Code Online (Sandbox Code Playgroud)
我将收到以下错误: 从字符串转换日期和/或时间时转换失败.
怎么会在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()
Run Code Online (Sandbox Code Playgroud)
更新 感谢大家的答案.我发现很难真正选择正确的答案,因为每个人都指出了一些对理解问题有用的东西.这绝对与执行的顺序有关.事实证明我的第一个查询正常工作,因为首先执行WHERE子句,然后执行SELECT.由于相同的原因,我的第二个查询失败(因为未过滤属性,执行相同的WHERE子句时转换失败).我的第三个查询是有效的,因为ID是索引(PK)的一部分,所以它优先,并且首先在该条件下钻取结果.
谢谢!
在Microsoft SQL Server 2008中,我有一个表,比如说myTable,包含大约600k行(实际上,它是连接其他几个表的结果,但我认为这并不重要).它的一个列,比如value数字类型(6,2).
简单的查询SELECT value FROM myTable ORDER BY value当然返回大约600k的数字,从1.01(即最低)开始,到70.00(最高)结束; 没有NULLs或其他值.
请注意,所有这些值都是数字和正数.但是,在调用时SELECT LOG(value) FROM myTable,我收到错误消息"发生了无效的浮点运算".
运行查询约3分钟后,始终显示此错误.将600k值复制到Excel并计算其LN()时,绝对没有问题.
我试过转换value成真实版或浮动版,这根本没用.最后我找到了一个解决方法:SELECT LOG(CASE WHEN value>0 THEN value ELSE 1 END) FROM myTable.这有效.但是,当所有价值观都是积极的时候呢?我试图取结果并将对数与Excel计算的对数进行比较 - 它们都是相同的(在某些行中只出现10 ^( - 15)或更小的顺序的差异,这几乎肯定是由不同的准确度给出的) .这意味着声明中的条件CASE总是正确的,我想.
有谁知道为什么会出现这个错误?任何帮助赞赏.谢谢.
背景:我试图在创建虚拟数据时获得一些随机的"十六进制"值,并提出了这种结构:
SELECT TOP 100
result = (CASE ABS(Binary_Checksum(NewID())) % 16
WHEN -1 THEN 'hello'
WHEN 0 THEN '0'
WHEN 1 THEN '1'
WHEN 2 THEN '2'
WHEN 3 THEN '3'
WHEN 4 THEN '4'
WHEN 5 THEN '5'
WHEN 6 THEN '6'
WHEN 7 THEN '7'
WHEN 8 THEN '8'
WHEN 9 THEN '9'
WHEN 10 THEN 'a'
WHEN 11 THEN 'b'
WHEN 12 THEN 'c'
WHEN 13 THEN 'd'
WHEN 14 THEN 'e'
WHEN 15 THEN 'f'
ELSE 'huh' …Run Code Online (Sandbox Code Playgroud) 我想我总是天真地认为SQL查询的select部分中的标量函数只会应用于满足where子句所有条件的行.
今天我正在调试供应商提供的一些代码并且让这个假设受到挑战.我能想到这个代码失败的唯一原因是,对于本应由WHERE子句过滤掉的数据调用了Substring()函数.但似乎在过滤发生之前应用了子串调用,查询失败.这是我的意思的一个例子.假设我们有两个表,每个表有2列,分别有2行和1行.每个中的第一列只是一个id.NAME只是一个字符串,NAME_LENGTH告诉我们名称中具有相同ID的字符数.请注意,只有具有多个字符的名称在LONG_NAMES表中具有相应的行.
NAMES: ID, NAME
1, "Peter"
2, "X"
LONG_NAMES: ID, NAME_LENGTH
1, 5
Run Code Online (Sandbox Code Playgroud)
如果我想要一个查询来打印最后3个字母的每个名字,我可能会先尝试这样的事情(现在假设是SQL Server语法):
SELECT substring(NAME,1,len(NAME)-3)
FROM NAMES;
Run Code Online (Sandbox Code Playgroud)
我很快就会发现这会给我一个错误,因为当它到达"X"时它将尝试在子串调用中使用负数,它将失败.我的供应商决定解决这个问题的方法是过滤掉字符串太短以至于len-3查询无效的行.他通过加入另一张桌子来做到这一点:
SELECT substring(NAMES.NAME,1,len(NAMES.NAME)-3)
FROM NAMES
INNER JOIN LONG_NAMES
ON NAMES.ID = LONG_NAMES.ID;
Run Code Online (Sandbox Code Playgroud)
乍一看,这个查询看起来可能有效.连接条件将消除任何具有足够短的NAME字段以使子字符串调用失败的行.
但是,根据我的观察,SQL Server有时会尝试计算表中所有内容的子字符串表达式,然后应用连接来过滤掉行.这应该是这样发生的吗?是否有记录的操作顺序,我可以在何时发现某些事情?它是特定于特定的数据库引擎还是SQL标准的一部分?如果我决定在我的NAMES表中包含一些谓词来过滤短名称(如len(NAME)> 3),SQL Server是否也可以选择在尝试应用子字符串后应用它?如果是这样,那么做一个子串的唯一安全方法似乎是将它包装在select中的"case when"构造中?
我们有一个SQL在ColumnA上执行CAST功能(到FLOAT).SQL有一个过滤器,它最终将间接过滤掉ColumnA中具有非数值的那些行.但是,由于我认为由于在并行中运行部分SQL,我相信CAST甚至应用于被过滤掉的行,这会导致SQL失败"无法将值转换为float ... "
我知道如果我通过添加查询提示运行一个proc
OPTION (MAXDOP 1)
Run Code Online (Sandbox Code Playgroud)
SQL按预期运行.我怀疑在1 proc上运行会强制应用过滤器以使用columnA中的非数值来清除行,以便其值的CASTING成功.我还发现使用查询提示
OPTION (FORCE ORDER)
Run Code Online (Sandbox Code Playgroud)
修复问题,我假设因为这也确保首先应用过滤器,并且我在一个柱面上运行的查询性能要好得多.
我倾向于使用第二个选项解决问题.如果我对这里发生的事情有任何误解,或者有人想阐述我的一般理解或提出建议,我将不胜感激.
我正在跑步
Microsoft SQL Server 2008 R2(RTM) - 10.50.1720.0(X64)2010年6月12日01:34:59版权所有(c)Windows NT 5.2上的Microsoft Corporation Enterprise Edition(64位)(Build 3790:Service Pack 2)
事后的想法:
似乎T-SQL具有以下函数来检查是否可以将字符串转换为特定数据类型.
IsFloat IsNumeric IsInteger等
我真的很烦恼我在数据库中找到的各种数据列中有多少列被定义为varchar(255).我想解决方案是"不要那样做!"