我正在尝试从其中一个(NVARCHAR)列在数值范围内的表中选择行。
SELECT ID, Value
FROM Data
WHERE ISNUMERIC(Value) = 1 AND CONVERT(FLOAT, Value) < 66.6
不幸的是,作为SQL规范的一部分,AND子句不必短路(并且不在MSSQL Server EE 2008上)。更多信息:Is the SQL WHERE clause short-circuit evaluated?
我的下一次尝试是尝试这样做,看看我是否可以延迟评估CONVERT
SELECT ID, Value
FROM Data
WHERE (CASE WHEN ISNUMERIC(Value) = 1 THEN CONVERT(FLOAT, Value) < 66.6 ELSE 0 END)
但我似乎无法使用&lt; (或任何比较)与CONVERT的结果。它失败并出现错误
Incorrect syntax near '<'.
我可以逃脱
SELECT ID, CONVERT(FLOAT, Value) AS Value
FROM Data
WHERE ISNUMERIC(Value) = 1
所以显而易见的解决方案是将整个select语句包装在另一个SELECT和WHERE中,并从内部select和filter中返回转换后的值。不幸的是,这是我的Linq-to-sql问题的来源。我不仅过滤了一个范围,而且过滤了很多,或者只是记录的存在(有一些日期范围选择和比较我遗漏了。 )
基本上我希望能够生成这样的东西:
SELECT ID, TypeID, Value
FROM Data
WHERE (TypeID = 4 AND ISNUMERIC(Value) AND CONVERT(Float, Value) < 66.6)
OR (TypeID = 8 AND ISNUMERIC(Value) AND CONVERT(Float, Value) > 99)
OR (TypeID = 9)
(每个选项中的其他一些条款。)如果我在内部选择中过滤掉非ISNUMERIC值,这显然不起作用。
正如我所提到的,我正在使用Linq-to-sql(和PredicateBulider)来构建这些查询但不幸的是
Datas.Where(x => ISNUMERIC(x.Value) ? Convert.ToDouble(x.Value) < 66.6 : false)
转换为此失败的初始问题。
WHERE (ISNUMERIC([t0].[Value]) = 1) AND ((CONVERT(Float,[t0].[Value])) < @p0)
我的最后一招必须是针对每个比较在同一桌面上的双重选择进行外连接,但这不是一个真正的想法解决方案。我想知道是否有人之前遇到过类似的问题?
答案 0 :(得分:8)
我不认为问题是AND本身,而是从NVARCHAR到FLOAT的转换
看一下以下示例
DECLARE @Table TABLE(
Value NVARCHAR(10)
)
INSERT INTO @Table SELECT '1'
INSERT INTO @Table SELECT '100'
INSERT INTO @Table SELECT 'A'
SELECT *
FROM @Table
WHERE ISNUMERIC(Value)= 1 AND CAST(CAST(Value AS VARCHAR(10)) AS FLOAT) > 50
SELECT *
FROM @Table
WHERE ISNUMERIC(Value)= 1 AND CAST(Value AS FLOAT) > 50
最后一个选择是我收到错误说明的地方
Msg 8114,Level 16,State 5,Line 13 将数据类型nvarchar转换为的错误 浮。
但是第一个选择正常。