首页 > 解决方案 > 如何使用表达式生成器创建带有日期的文件名,即使是每月的第一天

问题描述

我有一个每天早上运行的 SSIS 包,用于从 FTP 服务器中提取前几天的文件。我正在使用下面的代码使用上一个日期创建文件名。除非今天的日期是本月的第一天,否则一切都很好。例如,如果今天(2021 年 3 月 1 日)运行,则返回 name_of_file_20210328.xml.gz,但是昨天的日期是 2021 年 2 月 28 日而不是 3。我如何更新此日期以说明今天的日期是否是月初返回 mm - 1?

"name_of_file_" + (DT_STR,4,1252)(DATEPART("yyyy",GETDATE())) + (LEN((DT_STR,2,1252)(DATEPART("MM",GETDATE()))) == 2 ? (DT_STR,2,1252)(DATEPART("MM",GETDATE())) : "0" + (DT_STR,2,1252)(DATEPART("MM",GETDATE()))) + (LEN(( DT_STR,2,1252)(DATEPART("dd",DATEADD("day",-1, GETDATE())))) == 2 ? (DT_STR,2,1252)(DATEPART("dd",DATEADD(" day",-1, GETDATE()))) : "0" + (DT_STR,2,1252)(DATEPART("dd",DATEADD("day",-1, GETDATE())))) + ". xml.gz"

标签: ssisexpressionbuilder

解决方案


创建一个 DateTime 类型的变量 Yesterday。指定它使用表达式并使用以下表达式。这提供了一个可以测试的一致参考点,如果禁用表达式,则允许您指定边界/特殊情况检查的日期(如闰年 2020-03-01)

DATEADD("DAY", -1, @[System::StartTime])

接下来的步骤,特别是如果您刚开始,是在单独的变量中构建日期部分。在您的包中使用大量变量不需要任何额外费用,并且使故障排除变得更加容易。

添加一个字符串类型的新变量YearString

(DT_WSTR, 4)datepart("YYYY", @[User::Yesterday])

那很简单。

现在我们需要处理创建一个零左填充字符串。现在,您的表达式看起来像是在尝试确定日或月是否有 2 位数字。我有一个更干净的表达。

我们将把日/月转换为字符串,然后在前面加上一个零。对于 Jan-Sep,我们将得到一个 2 个字符的表达式,即 Oct-Dec,我们将有一个三个字符的表达式,例如 011。对于 Day,类似的位是 01-09 或 010-031。然后我们将从字符串中取出最后两个字符。对于两个字符串,它是无操作的,对于三个字符的变体,它得到了我们想要的。

将变量MonthString作为类型字符串添加到您的包中

RIGHT("0" + (DT_WSTR, 2)datepart("MONTH", @[User::Yesterday]), 2)

将变量DayString作为类型字符串添加到您的包中

RIGHT("0" + (DT_WSTR, 2)datepart("DAY", @[User::Yesterday]), 2)

花点时间看看你的变量集合。您可以看到您拥有正确构建 YYYYMMDD 字符串所需的所有构建块。如果出现问题,它的代码片段足够小,可以使用它。如果没有,请将其分解为更小的变量。

既然我们已经定义了 @Yesterday,然后从 Yesterday 构建 YearString、MonthString 和 DayString,我们所要做的就是将它们与连接+运算符结合在一起

回到变量好,创建字符串类型的@CurrentFileName

"name_of_file_" + @[User::YearString] + @[User::MonthString] + @[User::DayString] +  ".xml.gz"

结果为name_of_file_20210216.xml.gz

此答案中未解决,但您应该考虑的事情

如果今天作业根本没有运行(服务器严重故障、数据源关闭等),会发生什么?要获取和处理 2 天前的文件,您需要编辑此包,通过适用的任何更改审查流程运行它,部署到 prod,运行它,然后返回到昨天文件包的流程。

打字不好玩,更不用说考虑了。您当然不会更改服务器时间来欺骗表达式到昨天。

我提倡将运行日期传递给包(机制取决于您如何部署/运行包)。在这种情况下,根据我的经验,更改调用参数(因为没有“代码”已更改)比进行紧急代码更改要容易得多。


推荐阅读