I have a problem with ISNUMERIC
Function in SQL-server.
I have a table, which contains one column with nvarchar
type. In this column I have such a values 123
, 241
, ... and sometimes string values like LK
My Query:
WITH CTE AS (
SELECT *
FROM MyTable
WHERE ISNUMERIC([Column1]) = 1
)
SELECT *
FROM CTE
WHERE CAST(cte.Column1 AS INT) > 8000
but this query returns this error message:
error converting data type nvarchar 'LK' to int
my expectation is, that the Common table expression filter all rows, which Column1 are numeric and not string? Is it correct?
Why do I receive this error?
It has to do with how the query is parsed and executed. If adding a column as suggested by Devart is not possible, then using a temp table could be an alternate.
I think that below query is more efficient:
You can force to materialize CTE table by adding
TOP X
, to avoid SQL server optimize the where condition to make it "short-circuit" like behavior.This is actually no bug.
The CTE is a temporary view (or acts like a temporary view). So think on our query like querying a view. Most likely SQL will try first to go through all rows and get results from both scalars (isnumeric and the cast) then proceed to the filtering.
That being said, it will fail way before it will try to filter the data on the cast.
If you want to make it work just filter the data before in a temporary table or in a table variable.
The main problem is that SQL is a declarative language that imposes very little order on the operations. This is necessary to allow the engine to optimize the query.
One case where short-circuiting works is in a
case
statement. So you can try something like this:I can't tell you how the performance is going to work out, though. In general, you should really use normalized data when possible - it allows SQL databases to really shine :)