TSQL - 替换 isnumeric = 0
Posted
技术标签:
【中文标题】TSQL - 替换 isnumeric = 0【英文标题】:TSQL - replace isnumeric = 0 【发布时间】:2018-03-16 13:43:19 【问题描述】:我有一个 select 语句,并且在该 select 语句中我有几列用于执行基本计算(例如 [Col1] * 3.14)。但是,有时我会遇到非数字值,当这种情况发生时,整个存储过程会因为一行而失败。
我曾考虑过使用WHERE ISNUMERIC(Col1) <> 0
,但我会排除其他列中的信息。
TSQL 中是否有办法以某种方式将所有字符串替换为 NULL 或 0??
【问题讨论】:
使用 TRY_CAST() 而不是 ISNUMERIC() 来避免一些可能的麻烦。ISNUMERIC
回答了 nobody 想要回答的问题 - “这个字符串是否可以转换为至少一种数字数据类型,我不在乎哪些具体来说?”。很好。您想要一个 decimal
并且字符串只能转换为 money
类型这一事实确实为您带来了进步......
【参考方案1】:
类似...
SELECT blah1, blah2, blah3
CASE WHEN ISNUMERIC(Col1) = 1 THEN [Col1] * 3.14 ELSE NULL END as whatever
FROM your_table
也可以做个案例..
如果这是列中的预期值,非数字值应转换为数字或 NULL,并且 如果需要数字,则该列首先应该是数字数据类型,而不是字符数据类型,这允许出现这些类型的错误。【讨论】:
insert into your_table (blah1,blah2,blah3,Col1) values (1,2,3,'$4.0')
试试这个,你仍然会得到一个错误——ISNUMERIC
的一个例子。【参考方案2】:
我更喜欢 Try_Cast:
SELECT
someValue
,TRY_CAST(someValue as int) * 3.14 AS TRY_CAST_to_int
,TRY_CAST(someValue as decimal) * 3.14 AS TRY_CAST_to_decimal
,IIF(ISNUMERIC(someValue) = 1, someValue, null) * 3.14 as IIF_IS_NUMERIC
FROM (values
( 'asdf'),
( '2' ),
( '1.55')
) s(someValue)
【讨论】:
【参考方案3】:ISNUMERIC
是一种糟糕的方法,因为有太多东西标识为NUMERIC
,它们无法乘以非MONEY
数据类型。
https://www.brentozar.com/archive/2018/02/fifteen-things-hate-isnumeric/
这很失败,因为'-'是一个数字......
DECLARE @example TABLE (numerics VARCHAR(10));
INSERT INTO @example VALUES ('-')
SELECT CASE WHEN ISNUMERIC(numerics) = 1 THEN numerics * 3.14 ELSE NULL END
FROM @example;
改用TRY_CAST
(尽管修改您的 DECIMAL 精度以满足您的需要):
DECLARE @example TABLE (numerics VARCHAR(10));
INSERT INTO @example VALUES ('-')
SELECT TRY_CAST(numerics AS decimal(10,2)) * 3.14 FROM @example;
【讨论】:
"有太多东西被识别为 NUMERIC 而不是。" - 不对。任何导致ISNUMERIC
返回 1 的内容都可以转换为至少一种数字数据类型。问题是,我们不关心这种模糊的可能性——我们关心它是否可以转换为 特定 数字数据类型,这不是ISNUMERIC
回答的问题。例如。 select CONVERT(money,'-')
是一个完全有效的转换。但您不在乎,因为您不打算将 '-'
转换为 money
数据类型。【参考方案4】:
trycast 将测试特定类型
declare @T table (num varchar(20));
insert into @T values ('12'), ('3.14'), ('5.6E12'), ('$120'), ('-'), (''), ('cc'), ('aa'), ('bb'), ('1/5');
select t.num, ISNUMERIC(t.num) as isnumeric
, isnull(TRY_CONVERT(smallmoney, t.num), 0) as smallmoney
, TRY_CONVERT(float, t.num) as float
, TRY_CONVERT(decimal(18,4), t.num) as decimal
, isnull(TRY_CONVERT(smallmoney, t.num), TRY_CONVERT(float, t.num)) as mix
from @T t
num isnumeric smallmoney float decimal
-------------------- ----------- --------------------- ---------------------- ---------------------------------------
12 1 12.00 12 12.0000
3.14 1 3.14 3.14 3.1400
5.6E12 1 0.00 5600000000000 NULL
$120 1 120.00 NULL NULL
- 1 0.00 NULL NULL
0 0.00 0 NULL
cc 0 0.00 NULL NULL
aa 0 0.00 NULL NULL
bb 0 0.00 NULL NULL
1/5 0 0.00 NULL NULL
有趣的是最后还是失败了
【讨论】:
以上是关于TSQL - 替换 isnumeric = 0的主要内容,如果未能解决你的问题,请参考以下文章