SQL Server ISNUMERIC()澄清

时间:2017-11-09 21:38:27

标签: sql-server tsql ssms

我有一个表格X,上面有一个accountNo列表。该字段(accoutNo)是nvarchar(8)。 现在问题是我们有时会在这个字段中获得字符,我想将它转换为bigint。

很抱歉,我无法在此处以表格格式表示这一点。

我能够检查accountNo是否是数值:

select x.accountNo from x where ISNUMERIC(x.accountNo)=1

但是当我尝试仅在accountNo是数字时转换值时,我仍然不能,我很困惑:

select x.accountNo, convert(bigint,x.accountNo) from x where ISNUMERIC(x.accountNo)=1

我收到的具体错误:

  

Msg 8114,Level 16,State 5,Line 1转换数据类型时出错   nvarchar到bigint。

样本数据

accountNo  A0001001  A0001002  A0001003  /0005856  !0005046  ~0005872     A.005698 A/005623 A./00578 ./214536

3 个答案:

答案 0 :(得分:5)

您应该使用CAST()TRY_CAST()代替:

declare @test nvarchar(8) = '12345678'
select cast(@test as bigint) -- errors on failure
select try_cast(@test as bigint) -- returns null on failure

另外,重要的是指出ISNUMERIC()并不完美。来自docs

  

对于某些非数字字符,例如加号(+),减号( - )和有效货币符号(如美元符号($)),ISNUMERIC返回1。有关货币符号的完整列表,请参阅money和s​​mallmoney(Transact-SQL)。

出于这个原因,我不认为逻辑检查在这里是有价值的。最好在所有值上使用TRY_CAST(),无论是否存在字符,并以可预测的方式处理空响应。

答案 1 :(得分:2)

这是我经常遇到的问题。您收到错误的原因与查询引擎解析查询的顺序有关。基本上它是尝试在过滤器之前进行转换。

正如pim的回答中提到的,你可以通过使用try_cast来解决这个问题,或者如果你使用的是早期版本的SQL服务器,你可以在它周围包装一个case语句:

read -ra arrcourse < tmp2

答案 2 :(得分:1)

我在下面尝试查询并没有收到错误。我在SQL 2012和2014上进行了测试。

with c as (
    select 'A0001001' as acc union all
    select 'A0001002' as acc union all
    select 'A0001003' as acc union all
    select '/0005856' as acc union all
    select '!0005046' as acc union all
    select '~0005872' as acc union all
    select 'A.005698' as acc union all
    select 'A/005623' as acc union all
    select 'A./00578' as acc union all
    select './214536' as acc
)
select isnumeric(acc), convert(bigint, acc)
from c
where isnumeric(acc) = 1

请在您的数据库中尝试此操作,看看是否有任何错误。

这应该是一个评论,但加入评论太长了。希望它可以帮助你弄清楚你的问题。