【问题标题】:How can I turn a string into a decimal in SSIS using a derived column?如何使用派生列将字符串转换为 SSIS 中的小数?
【发布时间】:2021-06-28 13:49:20
【问题描述】:

我在 SSIS 工作以填充暂存区数据库。我要传输以下数据:

-------------------------------------------------------------------
| ShipName (String) | MaxContainers (int) | FuelCapacity (String) |
-------------------------------------------------------------------
| Ship1             | 1000                | 74.60 Liters          |
| Ship2             | 1500                | 121.28 Liters         |
-------------------------------------------------------------------

如您所见,FuelCapacity 列是一个包含数字和字母的字符串列。 新数据库的布局如下:

-------------------------------------------------------------------
| ShipName (String) | MaxContainers (int) | FuelCapacity (decimal)|
-------------------------------------------------------------------
| Ship1             | 1000                | 74.60                 |
| Ship2             | 1500                | 121.28                |
-------------------------------------------------------------------

我怎样才能做到这一点。我相信我需要为此使用派生列,但我不知道该怎么做。

PS:字符串列是数据库中的nvarchar数据类型

【问题讨论】:

  • 总是升吗?没有分升、千升等?
  • 它有时也是分升
  • 分升?我预计吨。
  • 我用的是testdata,所以不准确。

标签: sql ssis derived-column


【解决方案1】:

要重述问题,您需要根据第一个空格的位置拆分源列。我们需要保留前半部分的空格,然后将其转换为小数(或保留为字符串并使用 Gordon 的方法进行隐式转换)。在这一点上对我来说无关紧要。

当我看到这样的问题时,我想知道哪里会出错,这会影响我的设计。

考虑到这一点,我将在我的数据流中添加 3 个派生列表达式来解决这个问题。

设置

我在我的包中添加了一个 OLE DB 源并使用以下查询

SELECT '74.60 Liters' AS FuelCapacity
UNION ALL SELECT '121.28 Liters' AS FuelCapacity
UNION ALL SELECT '341.56 DeciLiters' AS FuelCapacity
UNION ALL SELECT '0.0 Liters'
UNION ALL SELECT NULL

没有提供最后 3 个,但似乎是域的合理值。

DER 空间

该组件的目的是识别入站文本中的空格。我将在数据流中添加一个名为 SpaceOrdinal 的新列,因为它将基于以下表达式

FINDSTRING([FuelCapacity]," ",1)

DER 获取第一个字符串

这个组件的目的是根据我们在上一步中获得的序数位置切出我们想要的数据。我创建了一个名为FirstString 的新列,因为它将包含第一条字符串数据。

LEFT([FuelCapacity],[SpaceOrdinal])

Der 转换为十进制

此步骤是可选的,因为您可以让隐式转换发生,也许您愿意/不希望它发生。新列,名为 LitersOfFuel;

(DT_NUMERIC,10,2)FirstString

这适用于提供的数据。

但是如果 0.0 升只是 0 升呢?此处的转换将失败,因为转换非常脆弱。但是您可以添加一个前导步骤,将数据转换为使用默认强制转换更好的东西。

【讨论】:

    【解决方案2】:

    您可以将数据加载到:

    insert into real_table (ShipName, MaxContainers, FuelCapacity)
        select ShipName, MaxContainers, FuelCapacity
        from staging;
    

    SQL Server 将隐式进行转换。我不是隐式转换的忠实拥护者,但如果您知道数据是正确的,那么一次性操作可能没有什么坏处。

    但是,您可能需要先验证数据:

    select fuelCapacity
    from staging
    where try_convert(numeric(?, ?), fuelCapacity) is null and
          fuelCapacity is not null;
    

    这将返回不正确的值。

    编辑:

    对于提供的数据,您显然需要字符串的前导数字:

    insert into real_table (ShipName, MaxContainers, FuelCapacity)
        select ShipName, MaxContainers,
               left(FuelCapacity, charindex(' ', FuelCapacity) - 1)
        from staging;
    

    【讨论】:

    • 我正在使用 SSIS 在数据库之间传输数据,所以我需要一个使用派生列的解决方案
    • @MissionarisMalleman 。 . .您正在将数据放入暂存区。只需从暂存区加载到决赛桌。但是,如果您想要一个正确类型的查询,只需使用try_convert(),这也在问题中(出于其他目的)进行了讨论。
    • 鉴于提供的数据,您的解决方案不会导致所有行都无法插入数据库吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-04-02
    • 2021-11-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-09
    相关资源
    最近更新 更多