Varchar 到数字的转换 - CLR 或 'e0'
Posted
技术标签:
【中文标题】Varchar 到数字的转换 - CLR 或 \'e0\'【英文标题】:Varchar to Numeric conversion - CLR or 'e0'Varchar 到数字的转换 - CLR 或 'e0' 【发布时间】:2012-07-01 15:48:16 【问题描述】:我想将 Varchar 列中的数据转换为 Numeric 数据类型 - 所以在转换之前,我调用 ISNUMERIC 函数来检查数据是否为数字,如果是,则将其转换为数字数据类型。但我面临一个问题 - IsNumeric 函数未按预期运行 -
- IsNumeric(x) returns true - when varchar value has both comma and a tab character (Char(9)),
- IsNumeric(x) returns false - when varchar value has only tab character and no comma
下面的SQL帮助解释-
DECLARE @propValue AS VARCHAR(50)
SET @propValue = '1,592 ' -- contains comma + tab (Char(9))
SELECT ISNUMERIC(@propValue) -- Returns 1
--If ISNUMERIC func returns true for this value, lets convert this Varchar value to Numeric
SELECT CAST(@propValue AS Numeric(19, 4)) -- :-( Error converting data type varchar to numeric.
我在谷歌上搜索并找到了解决这个问题的各种解决方案 -
--Solution 1: use 'e0'
SELECT ISNUMERIC(@propValue + 'e0') -- Returns 0
--Solution 2: remove comma before calling IsNumeric()
SELECT ISNUMERIC(REPLACE(@propValue, ',', '')) -- Returns 0
--Solution 3
--Call CLR function to parse Varchar value
在上述情况下推荐的解决方案是什么?为什么? 另外,如果有人能解释为什么 IsNumeric(x) 返回 false - 当 varchar 值只有制表符而没有逗号时,我将不胜感激?
谢谢!
【问题讨论】:
【参考方案1】:请记住,ISNUMERIC() = 1
并不意味着“可以转换为每种数字类型”,而是“可以转换为至少一种数字类型”。很多情况下,值可以转换为至少一种数字类型,但不是您想要的。一个更基本的例子:
IF ISNUMERIC(256) = 1
SELECT CONVERT(TINYINT, 256);
如果您有已知违规的字符串(例如制表符),那么为什么不也替换制表符呢?为什么不首先阻止垃圾数据进入这个值呢?
这可行,但它很丑:
DECLARE @x TABLE (propValue VARCHAR(50));
INSERT @x SELECT '1,592' + CHAR(9)
UNION ALL SELECT '55' + CHAR(9) + '32'
UNION ALL SELECT CHAR(9) + '7,452.32 '
UNION ALL SELECT 'foo'
UNION ALL SELECT '74';
SELECT CONVERT(NUMERIC(19,4),
LTRIM(RTRIM(REPLACE(REPLACE(propValue, CHAR(9), ''), ',', '')))
)
FROM @x
WHERE ISNUMERIC(LTRIM(RTRIM(REPLACE(REPLACE(propValue,
CHAR(9), ''), ',', ''))) + 'e0') = 1;
虽然不适用于您的确切问题,但我在 10 年前写了一个关于此的常见问题解答:http://classicasp.aspfaq.com/general/what-is-wrong-with-isnumeric.html
【讨论】:
感谢您的回复亚伦,是的,这是一种选择。你能建议一个好方法,我可以只指定白名单(可能是 0-9 个字符和一个小数),而不用担心长黑名单。 CLR 是一个不错的选择吗?还有其他的吗? @iniki 仅具有白名单,您只需拒绝任何包含白名单之外字符的值,或者根据对白名单的遵守情况一次构建一个字符的字符串(这也是变得复杂,因为如果你允许负值,那么'55-62'
是一个有效值吗?)。你的目标是什么?拒绝不良价值观或不惜一切代价尝试转换它们?正确的答案是首先停止将数字存储为字符串......
感谢您的回复亚伦,传入的数据目前不在我们的控制范围内:-(所以必须找到一种方法来处理无效的数字字符。我已经发布了另一个问题@***.com/questions/11348187/…请看如果你能帮忙。谢谢!【参考方案2】:
ISNUMERIC(RTRIM(LTRIM(x))) = 1
【讨论】:
RTRIM,LTRIM 删除空格但不删除制表符 :-(以上是关于Varchar 到数字的转换 - CLR 或 'e0'的主要内容,如果未能解决你的问题,请参考以下文章