将包含以科学计数法表示的数字的varchar强制转换为十进制时出错

时间:2019-02-27 23:08:10

标签: sql-server tsql

我目前正在从事ETL项目,该项目将mongoDB中的数据转换为关系数据库并存储在SQL Server中。我遇到的问题是mongoDB中同一字段中的一些数字存储为十进制(0.058823),有时使用科学计数法(5.8823e-02)。

当我使用Postgres时,任一种格式的值都以双精度值形式传递,并且在使用任一种格式进行查询时都没有问题。 SQL Server似乎并非如此。

当前所有数据都以varchar的形式传递,并且在同一张表的视图中,我正在使用以下代码:

CAST (CASE 
         WHEN [fieldname] LIKE '%e%' 
            THEN log([fieldname]) 
            ELSE [fieldname] 
      END AS DECIMAL(30, 20)) AS [FieldName1]

在我要转换为子字符串和强制转换的字段中也有列表,这需要使用CTE。这将我的代码从100多行变成了近600多行。想知道是否有更简单的方法?

非常感谢您能提供的任何帮助。

2 个答案:

答案 0 :(得分:4)

SQL Server支持科学计数法和“常规”小数。

这是一个简单的例子:

DECLARE @D decimal(10, 6) = 0.058823,
        @S decimal(10, 6) = 5.8823e-02

SELECT  @D As Regular, 
        @S As Scientific, 
        IIF(@D = @S, 1, 0) As AreEqual

此选择语句的结果是:

Regular     Scientific  AreEqual
0.058823    0.058823    1

但是,将varchar强制转换为十进制与常规十进制完美配合,但是使用科学计数法会引发错误:

DECLARE @SD varchar(10) = '0.058823',
        @SS varchar(10) = '5.8823e-02'                 

SELECT CAST(@SD AS decimal(10, 6)) As RegularString,
       CAST(@SS AS decimal(10, 6)) As ScientificString

引发此错误:

  

将数据类型varchar转换为数字时出错。

另一方面,强制转换为float可以很好地工作-因此,要获得小数,可以先转换为float再转换为十进制:

SELECT  CAST(@SD AS decimal(10, 6)) As RegularString,
        CAST(CAST(@SS AS float) AS decimal(10, 6)) As ScientificString

结果:

RegularString   ScientificString
0,058823        0,058823

答案 1 :(得分:0)

由于您的主要关注点似乎是代码膨胀(600行vs. 100行),因此您可以创建一个函数

CREATE FUNCTION dbo.GetDecimal(@input VARCHAR(32))
RETURNS DECIMAL(30,20)
AS
BEGIN
    RETURN CAST(CAST(@input AS FLOAT) AS DECIMAL (30, 20)) 
END

并在SELECT语句中为要转换的每个字段调用它,如下所示:

SELECT 
  dbo.GetDecimal(sfield1) as tfield1,
  dbo.GetDecimal(sfield2) as tfield2,
  ...
FROM ...

注意:对您的问题的第一条评论正确指出,您不应使用log()函数。而是,此用户函数执行中间强制转换,以在最终强制转换为十进制之前浮动。这是必要的,因为用科学计数法表示的字符串值不能直接转换为十进制。