T-Sql ISNUMERIC('45D-1') returns 1

谁都会走 提交于 2019-12-10 17:24:45

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!