path
此sql将导致错误
将varchar值“ hehe”转换为数据时转换失败 输入int。
但是表 series: [{
data: [{
y: 29.9,
id: 'min'
}, 71.5, 106.4, 129.2, 144.0, 176.0, 135.6, 148.5, {
y: 216.4,
id: 'max'
}, 194.1, 95.6, 54.4]
}, {
name: 'Fake annotations points',
// To make this series hidden and unaccessible for user.
type: 'scatter',
marker: {
enabled: false
},
showInLegend: false,
//
data: [{
x: 0,
y: 29.9,
id: '1'
}, {
x: 0,
y: 216.4,
id: '2'
}, {
x: 8,
y: 216.4,
id: '3'
}, {
x: 8,
y: 29.9,
id: '4'
}]
}],
annotations: [{
shapes: [{
type: 'path',
points: ['1', '2', '3', '4'],
}]
}]
});
的值不等于前面的表WITH tb_testl AS (
SELECT 1 AS id ,'hehe' AS value
UNION ALL
SELECT 1 AS id, '1' AS value
UNION ALL
SELECT 2 AS id, '2' AS value
UNION ALL
SELECT 2 AS id, '2' AS value
), tb_test2 AS (
SELECT CONVERT(INT , value) AS value FROM tb_testl WHERE id = 2
)
SELECT * FROM tb_test2 WHERE value = 2;
中的值'hehe'。而且我发现,如果我不附加语句tb_test2
,则此sql可以很好地工作。我已经尝试过tb_test1
函数,但没有用。
版本:mssql2008 R2
答案 0 :(得分:2)
SQL Server不保证语句的处理顺序(下面有一个例外)。也就是说,不能保证WHERE
过滤发生在SELECT
之前。或先评估一个CTE。之所以认为这是优势,是因为它允许SQL Server重新安排处理以优化性能(尽管我认为您会看到一个错误)。
显然,问题出在代码的这一部分:
tb_test2 AS (
SELECT CONVERT(INT, value) AS value
FROM tb_testl
WHERE id = 2
)
(嗯,实际上是引用tb_test2
的地方。)
发生的事情是SQL Server将CONVERT()
推送到要读取值的位置,因此在WHERE
子句处理之前 尝试了转换。因此,错误。
在SQL Server 2012+中,您可以使用TRY_CNVERT()
轻松解决此问题:
tb_test2 AS (
SELECT TRY_CONVERT(INT, value) AS value
FROM tb_testl
WHERE id = 2
)
但是,这在SQL Server 2008中不起作用。您可以使用以下事实:CASE
在处理顺序上确实有一些保证:
tb_test2 AS (
SELECT (CASE WHEN value NOT LIKE '%[^0-9]%' THEN CONVERT(INT, value)
END) AS value
FROM tb_testl
WHERE id = 2
)
答案 1 :(得分:1)
这部分陈述引起的错误
), tb_test2 AS (
SELECT CONVERT(INT , value) AS value FROM tb_testl WHERE id = 2
值的类型为 varchar ,并且'hehe'值不能转换为整数
WITH tb_testl AS (
SELECT 1 AS id ,'hehe' AS value
更新:sql尝试在您的语句中将所有值转换为整数。避免将错误改写为
WITH tb_testl AS (
SELECT 1 AS id ,'hehe' AS value
UNION ALL SELECT 1 AS id, '1' AS value
UNION ALL SELECT 2 AS id, '2' AS value
UNION ALL SELECT 2 AS id, '2' AS value
), tb_test2 AS (
SELECT value AS value FROM tb_testl WHERE id = 2
),
tb_test3 AS (
SELECT cast(value as int) AS value FROM tb_test2
)
SELECT * FROM tb_test3
答案 2 :(得分:1)
关于发生这种情况的原因:
有一个Logical Processing Order,它描述了子句的计算顺序。顺序是:
FROM
ON
JOIN
WHERE
GROUP BY
WITH CUBE or WITH ROLLUP
HAVING
SELECT
DISTINCT
ORDER BY
TOP
您SET SHOWPLAN_ALL ON
时也可以看到处理顺序。对于此查询,处理如下:
FROM
子句,它由硬编码值和常量组成。WHERE
子句。看起来好像有两个where子句(WHERE id = 2
和WHERE value = 2
)。 SQL Server对此有不同的看法,它只考虑一个WHERE
子句:WHERE CONVERT(INT , value) = 2 AND id = 2
。CONVERT
函数。因为两个WHERE
子句同时执行,所以hehe
的值不会从CONVERT
范围中过滤出来。
有效地,查询简化为:
SELECT CONVERT(INT, tb_testl.value) AS Cvalue
FROM (
SELECT 1 AS id
, 'hehe' AS value
UNION ALL
SELECT 1 AS id
, '1' AS value
UNION ALL
SELECT 2 AS id
, '2' AS value
UNION ALL
SELECT 2 AS id
, '2' AS value
) tb_testl
WHERE CONVERT(INT, tb_testl.value) = 2
AND tb_testl.id = 2
应阐明错误发生的原因。
使用SQL时,您无法以与命令式语言(如C)相同的方式读取代码。SQL代码行不一定(实际上实际上根本就根本没有)按照写入时的顺序执行。在这种情况下,认为内部位置在之前在外部位置执行是错误的。