我创建了一个小型 SSIS 解决方案来说明我的问题。不幸的是,我似乎无法在此处附加它,因此我将尝试解释。我可以将解决方案单独发送给人们。
SSIS SQL Server 2008。我有一个名为“Parent_Package”的包,其中包含一个变量:“User::Log_Path”。在设计期间,我为它分配了这个值:“C:\temp\Log_Design_Time”。该软件包配置了一个日志提供程序(简单文本文件)。日志文件的连接字符串有一个表达式:@[User::Log_Path] + "\" + @[System::PackageName] + [timestamp 表达式] + ".txt"。如您所见,我想为每个包执行创建一个新的日志文件。
如果我现在运行这个包,我将生成两个日志文件!从我创建包的时间开始,就会有一个时间戳。该文件只有标题字段,没有其他信息。第二个文件具有正确的时间戳和正确的输出信息:
似乎第一个文件是在验证期间创建的(即使我为日志文件连接管理器设置了 DelayValidation = True)。所以我的第一个问题是为什么会这样?这似乎不是正确的行为。现在为了进行下一步,我创建了一个子包“Package_Child”。我在父包中添加了一个执行包任务来运行这个子包。在子包中,我添加了一个与上面同名的变量:“User::Log_Path”。接下来,我给子包添加一个配置,使得“User::Log_Path”的值从父包变量中以同名方式获取。最后,我将日志提供程序添加到子包中,并以与上述父包相同的方式进行设置。
现在让我们再次运行父包。这一次我将得到三个日志文件:两个用于父级,一个用于子级:
对于我的下一个测试,我现在想更改日志文件的位置,因此我将父包中的 [User::Log_Path] 变量的值修改为“C:\temp\Log_Run_Time”。如果我现在运行,我将有四个日志文件!两个用于“Log_Run_Time”目录中的父包和两个用于子包 - 一个在“Log_Design_Time”中,一个在“Log_Run_Time”目录中:
这是怎么回事?最后,如果我只是删除原始的“Log_Design_Time”目录,我的子包将开始失败并抱怨它找不到指定的路径:
显然它仍在寻找之前指定的路径,但为什么呢?同样,我在所有连接管理器和包本身上设置了“延迟验证”= True。我很感激这方面的任何帮助。
谢谢!
PS这里是日志路径的完整表达式:@[User::Log_Path] + "\\" + @[System::PackageName] + "_" + (DT_STR, 4, 1252)DATEPART("yyyy", @[ System::ContainerStartTime]) + RIGHT("0" + (DT_STR, 2, 1252)DATEPART("mm", @[System::ContainerStartTime]), 2) + RIGHT("0" + (DT_STR, 2, 1252) )DATEPART("dd", @[System::ContainerStartTime]), 2) + "_" + RIGHT("0" + (DT_STR, 2, 1252)DATEPART("hh", @[System::ContainerStartTime]) , 2) + RIGHT("0" + (DT_STR, 2, 1252)DATEPART("mi", @[System::ContainerStartTime]), 2) + RIGHT("0" + (DT_STR, 2, 1252)DATEPART( "ss", @[System::ContainerStartTime]), 2) + ".txt"
我相信这与系统变量的时间和解释有关。
使用这个表达式来构建一个带有 _.log 的文件名,我一直在使用:
@[User::PathROOT]+"edw_logs\\"+ @[System::PackageName] + "_"+(DT_STR,4,1252) YEAR(GETDATE())+ RIGHT("00"+(DT_STR,2,1252) MONTH(GETDATE()),2)+RIGHT("00"+(DT_STR,2,1252) DAY(GETDATE()),2)+RIGHT("00"+(DT_STR,2,1252)DATEPART("Hour", @[System::StartTime]),2) + RIGHT("00"+ (DT_STR,2,1252)DATEPART("Minute", @[System::StartTime]) ,2) + RIGHT("00"+(DT_STR,2,1252)DATEPART("Second", @[System::StartTime]),2) +".log"
并且在验证和运行时创建了两个文件。
仅使用用户变量,它们在运行时被评估并且只创建一个文件。看到这个:
@[User::PathROOT]+"edw_logs\\"+ @[User::MyPackageName] + "_"+(DT_STR,4,1252) YEAR(GETDATE())+ RIGHT("00"+(DT_STR,2,1252) MONTH(GETDATE()),2)+RIGHT("00"+(DT_STR,2,1252) DAY(GETDATE()),2)+RIGHT("00"+(DT_STR,2,1252)DATEPART("Hour", GETDATE()),2) + RIGHT("00"+ (DT_STR,2,1252)DATEPART("Minute", GETDATE()) ,2) + RIGHT("00"+(DT_STR,2,1252)DATEPART("Second", GETDATE()),2) +".log"
我想我已经弄清楚了(至少部分)。似乎为了避免为子包创建重复的日志文件,“子”包中的“Log_Path”变量的值必须设为空白。如果没有值,验证过程将不会创建额外的文件,并将正确继承“父”中指定的值。这仍然不能完全解决“父”包的问题,因为如果没有为“Log_Path”变量指定任何值,我就无法从开发环境中运行它。我发现的唯一方法是将其设为空白,保存它,然后从命令行(DTExec)执行它,同时通过 SET 选项传递所需的变量值。这最终导致只有两个文件而不是四个。
我仍然不明白为什么验证过程(至少我认为它是验证过程)使用设计时值创建那些“额外”文件。这似乎是一种错误的行为。