问题
I have a T-Sql statement that is getting the next available number from a table. but the column is of type nvarchar. It dost have to be a number, But i still need to be able to get the next available number
so when i run the sql i try to only get numbers
WHERE
ISNUMERIC(myCol) AND CAST(REPLACE(myCol, N'0', N'') AS int)
but i get error
Conversion failed when converting the nvarchar value '45D-1' to data type int.
So i ran just
select ISNUMERIC('45D-1')
And to my surprise its true
I already wrote a replace for "." which makes sense, But why is "D" a number? And why cant sql cast it? And is there a function to really test if its a Int?
回答1:
INT
and NUMERIC
isn't the same. ISNUMERIC
is returning anything that could possibly be a numeric type (INT, BIGINT, DECIMAL, FLOAT, MONEY)
.
Example: SELECT ISNUMERIC('$')
This isn't an INT
but returns true because it is something that is correctly formatted as MONEY
. ISNUMERIC
also works on scientific notations.... SELECT ISNUMERIC('1e4')
would result to true. The point i'm making is don't trust ISNUMERIC
out right without understanding what it is evaluating, or all the possibilities.
回答2:
If 2012+ you can use Try_Convert()
select Try_Convert(int,'45D-1')
Returns
NULL
回答3:
select ISNUMERIC('45D-1' + '.e0')
Worked for me and also helped me on the "." issue
回答4:
You hit by chance one valid notation (I did not know this either):
SELECT CAST('45D-1' AS FLOAT) --4.5
SELECT CAST('45D-2' AS FLOAT) --0.45
SELECT CAST('45D-3' AS FLOAT) --0.045
SELECT CAST('45D+1' AS FLOAT) --450
SELECT CAST('45D+3' AS FLOAT) --45000
Produces the same results as
SELECT CAST('45e-1' AS FLOAT)
SELECT CAST('45e-2' AS FLOAT)
SELECT CAST('45e-3' AS FLOAT)
SELECT CAST('45e+1' AS FLOAT)
SELECT CAST('45e+3' AS FLOAT)
Obviously there is a scientific notation using the letter d
in the same way as the more usual e
.
Just add .0
to your string and ISNUMERIC
will return no number
DECLARE @s VARCHAR(100)='45D-1';
SELECT ISNUMERIC(@s+'.0')
(Works only, if your numbers haven't got decimals already...)
UPDATE
You might use PATINDEX
to search for any occurance of a character not 0-9
:
DECLARE @s VARCHAR(100)='45D-1';
SELECT CASE WHEN PATINDEX('%[^0-9]%',@s)>0 THEN 'Nope!' ELSE 'Yeah!' END AS IsInt
回答5:
T-SQL works differently from other languages. Evaluation depends on query plan. It's free to evaluate them in any order that it sees as the most effective.
Use derivated qry like:
select *
from (
select *
from tbl
where isnumeric(myCol) = 1
-- where yourfunction(myCol) = 1 -- where your function returns null on non-numeric
) t
where myCol = 8
In your funtion you have to remove .#$A-Z,+-... But in some cases you want sciencist notation with D or E. Fastest is CRL function for this purposes.
来源:https://stackoverflow.com/questions/40898509/t-sql-isnumeric45d-1-returns-1