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;
this sql will cause error
Conversion failed when converting the varchar value 'hehe' to data type int.
but the table tb_test2
dosen't have the value 'hehe' which is in the anthor table tb_test1
. And I found that this sql will work well if I don't append the statement WHERE value = 2;
.I've tried ISNUMBERIC
function but it didn't work.
version:mssql2008 R2
3条答案
按热度按时间s5a0g9ez1#
With respect to the why this occurs:
There is a Logical Processing Order, which describes the order in which clauses are evaluated. The order is:
You can also see the processing order when you
SET SHOWPLAN_ALL ON
. For this query, the processing is as follows:FROM
clause, which consists of hard coded values, hence the constants.WHERE
clause. While it looks like there are two where clauses (WHERE id = 2
andWHERE value = 2
). SQL Server sees this differently, it considers a singleWHERE
clause:WHERE CONVERT(INT , value) = 2 AND id = 2
.CONVERT
function in the select.Because both
WHERE
clauses are executed simultaneously, thehehe
value is not filtered out of theCONVERT
scope.Effectively, the query is simplified to something like:
Which should clarify why the error occurs.
With SQL, you cannot read code in the same way as imperative languages like C. Lines of SQL code are not necessarily (mostly not at all, in fact) executed in the same order it is written in. In this case, it's an error to think the inner where is executed before the outer where.
30byixjq2#
SQL Server does not guarantee the order of processing of statements (with one exception below). That is, there is no guarantee that
WHERE
filtering happens before theSELECT
. Or that one CTE is evaluated before another. This is considered an advantage because it allows SQL Server to rearrange the processing to optimize performance (although I consider the issue that you are seeing a bug).Obviously, the problem is in this part of the code:
(Well, actually, it is where
tb_test2
is referenced.)What is happening is that SQL Server pushes the
CONVERT()
to where the values are being read, so the conversion is attempted before theWHERE
clause is processed. Hence, the error.In SQL Server 2012+, you can easily solve this using
TRY_CNVERT()
:However, that doesn't work in SQL Server 2008. You can use the fact that
CASE
does have some guarantees on the order of processing:c90pui9n3#
error caused by this part of statement
value has type of varchar and 'hehe' value cannot be converted to integer
UPDATE: sql try convert all value(s) to integer in you statement. to avoid error rewrite statement as