使用 ssis 派生列将 yymmdd 转换为日期时间

0 datatypes ssis type-conversion

以下是表示出生日期 (yymmdd) 的字符串。我想将其转换为日期时间格式并使用 ssis 加载到数据库中。我该怎么做?在我的派生列中,我有(DT_DATE)(SUBSTRING([Drv DOB],1,2) + "-" + SUBSTRING([Drv DOB],3,2) + "-" + SUBSTRING([Drv DOB],5,2)),但它不起作用。

  • 470324
  • 470324
  • 470209
  • 101
  • 0

bil*_*nkc 7

数据流

这是我用来解决您的问题的一般方法。

数据流

我从您的源数据开始并添加了一些其他条件 - NULL 以及 14 年和 15 年,以确保我以后的逻辑是正确的。

SELECT 
    D.DrvDOB
FROM
(
    VALUES
    ('470324')
,   ('470324')
,   ('470209')
,   ('140209')
,   ('150209')
,   ('101')
,   ('0')
,   (NULL)
) D(DrvDOB);
Run Code Online (Sandbox Code Playgroud)

这看起来像是很多工作,但对我来说,这是最易于维护的方法。如果出现问题,我可以简单地在派生列之间进行检查并找到逻辑的失败部分。许多人错误地认为数据流上的组件数量会减少处理时间。反之亦然,详情请参阅文末的 sqlblog 文章。

创建一个名为IsValidLengthThis的列将为我们提供一个布尔值来告诉我们是否甚至需要尝试从字符串中解析年、月和日。我确保我们没有 NULL 值并且长度为 6。否则,我们将标记为无效

!IsNull([DrvDOB]) && LEN([DrvDOB]) == 6
Run Code Online (Sandbox Code Playgroud)

然后,我将使用解析的年、月和日生成另外 3 个字符串列(der_Year、der_Month、der_Day)。否则,我将使用 00 作为我的值。同样,我只尝试解析有效​​的字符串。

(IsValidLength) ? SUBSTRING([DrvDOB], 1, 2) : "00"
(IsValidLength) ? SUBSTRING([DrvDOB], 3, 2) : "00"
(IsValidLength) ? SUBSTRING([DrvDOB], 5, 2) : "00"
Run Code Online (Sandbox Code Playgroud)

现在是真正有趣的部分,确定实际年份。由于您的领域被称为出生日期,我假设没有未来的日期记录 - 如果您有心理数据,我深表歉意。我选择了 SQL Server、.NET 库和 COM 使用的路线,并有一个规定的年份用作标记为 19XX 与 20XX 之间的标记。我创建了一个名为TwoDigitYearCutoff2014的 SSIS 变量。简而言之,从 00 到 14 解析的任何年份都将被标记为 21 世纪,而其余的则留在 20 世纪。根据需要调整此值。

回到我的数据流中,我创建了另一列,这个 der_ActualYear 将是 4 位数的年份。

(@[User::TwoDigitYearCutoff] / 100 
- ((DT_I4)der_Year > @[User::TwoDigitYearCutoff] % 100 ? 1 : 0)) 
* 100 + (DT_I4)der_Year
Run Code Online (Sandbox Code Playgroud)

在这一点上,我们知道全年、月份和日期以及这些数据是否有用。最后的部分是将它们放在一起并使其成为实际的日期。我构建了一个 YYYY-MM-DD 字符串并将其转换为日期。否则,我将 NULL 作为日期(以使我的元数据一致)

(IsValidLength) ? (DT_DATE) ((DT_WSTR, 4) [der_ActualYear] 
+ "-" + [der_Month] + "-" + [der_Day]) : NULL(DT_DATE)
Run Code Online (Sandbox Code Playgroud)

您现在可以将 der_DrvDOB 连接到您的目标目的地,知道您有一个有效的日期或一个 NULL。

结果

正如预期的那样,有效日期或空

结果

比尔

Biml(商业智能标记语言)描述了商业智能平台。在这里,我们将使用它来描述 ETL。BIDS Helper是 Visual Studio/BIDS/SSDT 的免费插件,解决了它的许多缺点。具体来说,我们将使用将描述 ETL 的 Biml 文件转换为 SSIS 包的功能。这有一个额外的好处,它为您提供了一种机制,能够准确地生成我所描述的解决方案,而不是单击许多乏味的对话框。

<Biml xmlns="http://schemas.varigence.com/biml.xsd">
    <!-- 74383 -->
    <Connections>
        <OleDbConnection ConnectionString="Provider=SQLNCLI11;Data Source=localhost\dev2014;Integrated Security=SSPI;Initial Catalog=tempdb" Name="CM_OLE" />
    </Connections>
    <Packages>
        <Package Name="dba_74383" ConstraintMode="Linear">
            <Variables>

                <Variable DataType="Int32" Name="TwoDigitYearCutoff">2014<Annotations>
                    <Annotation AnnotationType="Description">Use the two digit year cutoff to specify an integer from 1753 to 9999 that represents the cutoff year for interpreting two-digit years as four-digit years</Annotation>
                </Annotations>
            </Variable>
            </Variables>
            <Tasks>
                <Dataflow Name="DFT Make Dates">
                    <Transformations>
                        <OleDbSource ConnectionName="CM_OLE" Name="OLE_SRC Gen data">
                            <DirectInput>SELECT 
    D.DrvDOB
FROM
(
    VALUES
    ('470324')
,   ('470324')
,   ('470209')
,   ('140209')
,   ('150209')
,   ('101')
,   ('0')
,   (NULL)
) D(DrvDOB);</DirectInput>
                        </OleDbSource>
                        <!--
                            Test whether we have minimally valid data
                        -->
                        <DerivedColumns Name="DER IsValidLength">
                            <Columns>
                                <Column Name="IsValidLength" DataType="Boolean"><![CDATA[!IsNull([DrvDOB]) && LEN([DrvDOB]) == 6 ]]></Column>
                            </Columns>
                        </DerivedColumns>
                        <!--
                            Extract the year
                        -->
                        <DerivedColumns Name="DER ExtractYear">
                            <Columns>
                                <Column Name="der_Year" DataType="String" Length="2">(IsValidLength) ? SUBSTRING([DrvDOB], 1, 2) : "00"</Column>
                            </Columns>
                        </DerivedColumns>
                        <!--
                            Extract the Month
                        -->
                        <DerivedColumns Name="DER ExtractMonth">
                            <Columns>
                                <Column Name="der_Month" DataType="String" Length="2">(IsValidLength) ? SUBSTRING([DrvDOB], 3, 2) : "00"</Column>
                            </Columns>
                        </DerivedColumns>

                        <!--
                            Extract the day
                        -->
                        <DerivedColumns Name="DER ExtractDay">
                            <Columns>
                                <Column Name="der_Day" DataType="String" Length="2">(IsValidLength) ? SUBSTRING([DrvDOB], 5, 2) : "00"</Column>
                            </Columns>
                        </DerivedColumns>

                        <!-- 
                            Guess at year based on cutoff date. Assume historical data and not future dated
                            since this is DOB. For supplied value of 2014, 
                            if 14 is seen, it will be 2014
                            if 15 is seen, it will be 1915

                            http://technet.microsoft.com/en-us/library/ms189577(v=sql.105).aspx 
                            A two-digit year that is less than or equal to the last two digits of the cutoff year is 
                            in the same century as the cutoff year. A two-digit year that is greater than the last 
                            two digits of the cutoff year is in the century that precedes the cutoff year. For example, 
                            if two digit year cutoff is 2049 (the default), the two-digit year 49 is interpreted as 2049 
                            and the two-digit year 50 is interpreted as 1950.

                            /sf/ask/141699141/
                            this.TwoDigitYearMax / 100 - (year > this.TwoDigitYearMax % 100 ? 1 : 0)) * 100 + year

                            @[User::TwoDigitYearCutoff]) / 100 - ((Int32) [der_Year] > @[User::TwoDigitYearCutoff]) % 100 ? 1 : 0)) * 100 + (Int32) [der_Year]
                        -->
                        <DerivedColumns Name="DER Guess at year">
                            <Columns>
                                <Column DataType="Int32" Name="der_ActualYear"><![CDATA[(@[User::TwoDigitYearCutoff] / 100 - ((DT_I4)der_Year > @[User::TwoDigitYearCutoff] % 100 ? 1 : 0)) * 100 + (DT_I4)der_Year]]></Column>
                            </Columns>
                            <Annotations>
                                <Annotation AnnotationType="Description">This might be overkill, but it sure was fun</Annotation>
                            </Annotations>
                        </DerivedColumns>

                        <!--
                            Put it all together
                        -->
                        <DerivedColumns Name="DER Make valid date">
                            <Columns>
                                <Column Name="der_DrvDOB" DataType="Date">(IsValidLength) ? (DT_DATE) ((DT_WSTR, 4) [der_ActualYear] + "-" + [der_Month] + "-" + [der_Day]) : NULL(DT_DATE) </Column>
                            </Columns>
                        </DerivedColumns>

                        <DerivedColumns Name="DER bitbucket">

                        </DerivedColumns>
                    </Transformations>
                </Dataflow>
            </Tasks>
        </Package>
    </Packages>
</Biml>
Run Code Online (Sandbox Code Playgroud)

参考