请注意http://sqlfiddle.com/#!3/6f14c/7
这是架构:
CREATE TABLE tmp1 (
ts DATETIME NOT NULL,
message NVARCHAR(128) NOT NULL
)
INSERT INTO tmp1 (ts,message) VALUES
('2015-06-24 00:28:18', '121a'),
('2015-06-24 00:30:18', '28.315b')
这是SQL语句:
;with data as (
select ts,CONVERT(FLOAT, replace(message,'a','')) seconds from tmp1
where message LIKE '%a'
)
select * from data where seconds > 100
运行它会产生将数据类型nvarchar转换为float的错误。
为什么?
答案 0 :(得分:2)
SQL Server不保证表达式的评估顺序。发生的事情是转换是在过滤之前发生的,因为它被推送到读取数据的进程部分。
CTE和子查询不会影响此优化。在单个查询中,在早期版本的SQL中绕过它的唯一方法是使用case
:
select ts,
(case when isnumeric(replace(message, 'a', '')) = 1
then CONVERT(FLOAT, replace(message,'a',''))
end)
from tmp1
where message LIKE '%a' and seconds > 100;
在SQL Server 2012+中,您可以改为使用try_convert()
:
with data as (
select ts, try_convert(FLOAT, replace(message,'a','')) as seconds
from tmp1
where message LIKE '%a'
)
select * from data where seconds > 100
答案 1 :(得分:0)
戈登的回答实际上是正确的!或者,我认为您也可以在SQL Server中使用trim函数来执行此操作:
;WITH data
AS (
SELECT ts
,CONVERT(FLOAT, ltrim(rtrim(replace(message, 'a', '')))) seconds
FROM tmp1
WHERE message LIKE '%a'
)
SELECT *
FROM data
WHERE seconds > 100