根据SSDT / SSIS中TableA的值从TableB加载TableC

时间:2014-09-23 22:25:30

标签: ssis sql-server-data-tools ssis-2012

我有3张桌子 -

      --server 1
      CREATE TABLE TableA (GROUP_ID INT
                          ,STATUS VARCHAR(10))
      --server 2
      CREATE TABLE TableB (GROUP_ID INT 
                          ,NAME VARCHAR(10)
                          ,STATE VARCHAR(50)
                          ,COMPANY VARCHAR(50))
      -- server 1
      CREATE TABLE TableC (GROUP_ID INT
                          ,NAME VARCHAR(10)
                          ,STATE VARCHAR(50)
                          ,COMPANY VARCHAR(50))

示例数据

      INSERT INTO TableA (1, 'READY'),(2,'NOT READY),(3,'READY'),(4,'NOT READY')
      INSERT INTO TableB (1, Mike, 'NY', 'aaa'), (1, Rick, 'OK','bbb'), (2, Smith, 'TX','ccc'), (3, Nancy, 'MN','bbb'), (4, Roger, 'CA','aaa')

我正在尝试构建一个SSDT(SSIS 2012)程序包,以便从表B中加载Ta​​bleC中的数据,仅用于TableA中具有STATUS ='READY'的GROUP_ID并更改STATUS ='LOADED'

我需要通过使用TableA-GROUP_ID和STATUS的项目级参数或变量来实现这一点,因为我将为大约60个表执行此操作,并且这些值可能会更改。

我必须构建一个SSIS包,这是一个要求。 使用链接服务器不是首选。除非通过SSIS无法实现。

任何帮助都将不胜感激。

1 个答案:

答案 0 :(得分:1)

由于这两个表位于不同的服务器上,因此您可以使用两个源创建数据流。您需要为两个数据库设置连接管理器,然后将一个Source指向包含TableA的数据库,将另一个指向包含TableB的数据库。完成此操作后,您可以将两者合并为合并加入,然后使用条件拆分丢弃不具有所需值的记录。它最终看起来有点像这样:

Example data flow

首先,您需要按照已经讨论过的方式设置源。但是,由于您要使用合并连接,因此您需要对来自源的输出进行排序。您可以使用Sort转换在SSIS中执行此操作,但是您最好只在源语句中的SELECT语句中构建ORDER BY子句,然后告诉SSIS输出已排序:

  • 右键单击每个Source,然后选择Show Advanced Editor。
  • 转到“输入和输出属性”选项卡。
  • 选择OLE DB Source Output,然后将右侧的IsSorted设置为True。
  • 展开“OLE DB源输出”,然后展开“输出列”。
  • 点击您要排序的列(可能是GROUP_ID),并将SourceKeyPosition设置为1.

这是最后一点的图片,以防你完全失去了 - 如果你不习惯它,它可能会在SSIS的某些地方徘徊:

SortKeyPosition picture

由于您要更改的STATUS值可能会加载,因此可以在“项目参数”中进行设置。只需从解决方案资源管理器中转到该页面,然后单击以添加新参数。你应该得到这样的东西:

enter image description here

当您使用2012时,您可以在SSMS中发布后配置此值,从而无需重新设置此值或创建配置文件。

设置条件分割时,您有几个选项。如果您将来可能希望将包含其他STATUS值的行发送到其他表中,那么您应该查找STATUS值为READY的情况,但如果您只关心READY行,您也可以按照我的方式进行操作。这里:

Conditional Split setup

当您将条件分割的输出拖动到目标时,它会询问您要使用哪个输出。如果您以与我相同的方式进行设置,请使用条件拆分默认输出,并且它将通过所有不符合您已声明的条件的行。< / p>

如果您需要在重新加载数据时更新数据值,则它取决于您希望更新显示的位置。如果要单独保留TableA和TableB,但更改TableC中的值,则可以在“条件性拆分”之后和“目标”之前设置“派生列”转换。然后,您可以将STATUS列中的值替换为您设置的值(可以参数化,如上所述):

Derived Column with replace

如果要更新TableA中的STATUS字段,那么您应该返回到控制流,在您正在处理的数据流之后,添加一个连接到数据库持有的执行SQL任务TableA,它运行一个简单的SQL更新语句。

如果这将在营业时间之外运行,并且您知道在此期间不会有任何新行,您只需更新当前具有状态为READY的所有行。如果您需要更精确地更新行,因为在您工作时情况可能会继续发生变化,那么您可能需要重新考虑这一点 - 一个选项是获取您想要在开始时更新的所有GROUP_ID值,将其存储在变量中,并将该变量用作Source select语句和Execute SQL Task更新语句中的参数。你也可以选择在循环中工作,但这显然要比批量操作行慢很多。


这部分来自我在问题更新前的原始答案,但我会留在这里,以防其他人有用:

如果表(A和B)位于同一个数据库中,而不是条件性拆分,则可以将源设置为将表A连接到表B的select语句,并且具有仅选择状态为READY的行:

select GROUP_ID, NAME, STATE, COMPANY
  from TableA a
inner join TableB b
    on a.GROUP_ID = b.GROUP_ID
 where a.STATUS = 'READY';