我正在处理审核日志,并希望忽略NULL值更改为零(或保持为NULL)的条目。无论记录的字段类型如何,旧值和新值都保存在NVARCHAR字段中。为了将一个新值CAST为十进制,以确定它是否为零,我需要限制该字段的ISNUMERIC返回1的情况。
我已经使用了这个奇怪的SQL - 但确信必须有更好的方法。
WHERE MessageDesc LIKE 'poitem%'
AND NOT(OldValue IS NULL AND 0.0 =
CASE
WHEN ISNUMERIC(NewValue) = 1 THEN CAST(NewValue AS DECIMAL(18,4))
WHEN NewValue IS NULL THEN 0.0
ELSE 1.0
END)
有什么建议吗?
答案 0 :(得分:1)
SQL Server 2012添加了一个Try_Convert函数,如果该值无法作为给定类型转换,则返回NULL。 http://technet.microsoft.com/en-us/library/hh230993.aspx
WHERE NOT (OldValue is Null AND
(NewValue is null OR try_convert(float, NewValue) = 0.0)
)
如果使用2012年之前的版本,请查看Damien_The_Unbeliever的回答:Check if a varchar is a number (TSQL) ...根据Aaron的评论,这在所有情况下都不起作用。
由于您使用的是SQL 2008,因此它出现了isnumeric的组合,并且上面链接中Damien的修改版本的答案将起作用。您在问题中的当前解决方案会出现“。”,“ - ”,货币符号($等)以及“1e4”等科学记数法等问题。
尝试使用SQL 2008(这里是带有测试用例的SQLFiddle:http://sqlfiddle.com/#!3/fc838/3):注意:如果文本有逗号(例如:1,000)或带有parens的会计符号,此解决方案不会将文本值转换为数字(例如:使用“(1)”表示“-1”),因为SQL Server在尝试强制转换为十进制时会抛出错误。
WHERE t.OldValue is null
AND
(
t.NewValue is null
OR
0.0 =
case
when isnumeric(t.NewValue) = 1
--Contains only characters that are numeric, negative sign, or decimal place.
--This is b/c isnumeric will return true for currency symbols, scientific notation, or '.'
and not (t.NewValue like '%[^0-9.\-\+]%' escape '\')
--Not other single char values where isnumeric returns true.
and t.NewValue not in ( '.', '-', '+')
then cast(t.NewValue as decimal(18,4))
else null --can't convert to a decimal type
end
)
答案 1 :(得分:0)
避免使用ISNUMERIC(),因为'。'。
会出现问题-- Dot comes up as valid numeric
select
ISNUMERIC('.') as test1,
ISNUMERIC('1A') as test2,
ISNUMERIC('1') as test3,
ISNUMERIC('A1') as test4
-- Results window (text)
test1 test2 test3 test4
----------- ----------- ----------- -----------
1 0 1 0
改用COALESCE()。
WHERE MessageDesc LIKE 'poitem%'
AND
NOT (OldValue IS NULL AND
CAST(COALESCE(NewValue, '0') AS DECIMAL(18,4)) = 0)