【问题标题】:How do I split flat file data and load into parent-child tables in database?如何拆分平面文件数据并加载到数据库中的父子表中?
【发布时间】:2011-07-12 01:10:23
【问题描述】:

我有需要导入父子表的非规范化数据(来自文件)。源数据是这样的:

Account#    Name        Membership    Email
101         J Burns     Gold          alpha@foo.com
101         J Burns     Gold          bravo@foo.com
101         J Burns     Gold          charlie@yay.com
227         H Gordon    Silver        red@color.com
350         B Clyde     Silver        italian@food.com
350         B Clyde     Silver        mexican@food.com

我应该使用 SSIS 的哪些部分、部分或策略将前三列读入父表,并将第四列(电子邮件)读入子表?对于允许使用的父密钥,我有几个选项:

  • 直接使用Account#作为主键
  • 在导入过程中使用由 SSIS 生成的代理键
  • 配置身份主键

我确定我已经按难度递增的顺序列出了我的主键选项。我有兴趣知道如何做第一个和最后一个选项 - 我将推断如何实现中间选项。再次强调,我对 SSIS 解决方案很感兴趣。我正在寻找使用 SSIS 语言的答案,而不是程序、技术中立的答案。

我的问题有点类似于another SO question,答案是模糊的可行性。希望能给出更详细的指导。我已经知道如何通过创建“分段”中间步骤来解决这个问题,其中父子分离实际上是用直接 SQL 处理的。但是,我很好奇如何在没有这种中间步骤的情况下做到这一点。

在我看来,这种导入非常普遍,以至于会有一种广为人知的公式化方式来处理它——这是 SSIS 擅长的一种技术。到目前为止,我还没有看到任何直接的答案。

Update #1:基于cmets,我对样本数据进行了更明显的非规范化调整。我还从“平面文件”中删除了“平面”,这样语义就不会干扰问题。

Update #2:我对使用 SSIS 语言的解决方案更加感兴趣。

【问题讨论】:

  • 我在您提供的数据中看不到父子关系。它看起来像一对多场景中的第二个表。
  • +1 @Steve - 这不是非规范化或平坦的。
  • 我已根据您的 cmets 调整了问题。有建议的答案吗?

标签: sql-server sql-server-2008 import ssis etl


【解决方案1】:

这是加载父子数据时可以考虑的一种可能选项。此选项包括两个步骤。在第一步中,读取源文件并将数据写入父表。在第二步骤中,再次读取源文件并使用查找转换获取父信息,以便将数据写入子表。以下示例使用问题中提供的数据。此示例是使用 SSIS 2008 R2 和 SQL Server 2008 数据库创建的。

分步流程:

  1. 创建一个名为 Source.txt 的示例平面文件,如屏幕截图 #1 所示。

  2. 在 SQL 数据库中,使用 SQL 脚本 部分中提供的脚本创建两个名为 dbo.Parentdbo.Child 的表。这两个表都有一个自动生成的标识列。

  3. 在包上,放置OLE DB connection 以连接到 SQL Server,并放置 Flat File connection 以读取源文件,如屏幕截图 #2 所示。如屏幕截图 #3 - #9 所示配置平面文件连接。

  4. 在“控制流”选项卡上,放置两个Data Flow Tasks,如屏幕截图#10所示。

  5. 在名为 Parent 的数据流任务中,放置平面文件源、排序转换和 OLE DB 目标,如屏幕截图 #11 所示。

  6. 如屏幕截图 #12 和 #13 所示配置平面文件源。我们需要读取平面文件源。

  7. 如屏幕截图 #14 所示配置排序转换。我们需要消除重复值,以便仅将唯一记录插入父表dbo.Parent

  8. 如屏幕截图 #15 和 #16 所示配置 ole db 目标。我们需要将数据插入到父表dbo.Parent中。

  9. 在名为 Child 的数据流任务中,放置平面文件源、查找转换和 OLE DB 目标,如屏幕截图 #17 所示。

  10. 如屏幕截图 #12 和 #13 所示配置平面文件源。此配置与上一个数据流任务中的平面文件源相同。

  11. 如屏幕截图 #18 和 #20 所示配置查找转换。我们需要使用文件中存在的其他键列从表 dbo.Parent 中找到父 ID。这里的关键列是帐户、名称和电子邮件。如果文件恰好有一个唯一的列,您可以单独使用该列来获取父 ID。

  12. 如屏幕截图 #21 和 #22 所示配置 ole db 目标。我们需要将 Email 列和 Parent id 一起插入到表 dbo.Child 中。

  13. 屏幕截图#23显示了执行包之前表中的数据。

  14. 屏幕截图 #24 和 #25 显示示例包执行。

  15. 屏幕截图 #26 显示了包执行之后表中的数据。

希望对您有所帮助。

SQL 脚本:

CREATE TABLE [dbo].[Child](
    [ChildId] [int] IDENTITY(1,1) NOT NULL,
    [ParentId] [int] NULL,
    [Email] [varchar](21) NULL,
CONSTRAINT [PK_Child] PRIMARY KEY CLUSTERED ([ChildId] ASC)) ON [PRIMARY]
GO

CREATE TABLE [dbo].[Parent](
    [ParentId] [int] IDENTITY(1,1) NOT NULL,
    [Account] [varchar](12) NULL,
    [Name] [varchar](12) NULL,
    [Membership] [varchar](14) NULL,
CONSTRAINT [PK_Parent] PRIMARY KEY CLUSTERED ([ParentId] ASC)) ON [PRIMARY]
GO

屏幕截图 #1:

屏幕截图 #2:

截图#3:

屏幕截图 #4:

屏幕截图 #5:

屏幕截图 #6:

截图#7:

截图#8:

屏幕截图 #9:

屏幕截图 #10:

屏幕截图 #11:

屏幕截图 #12:

屏幕截图 #13:

屏幕截图 #14:

屏幕截图 #15:

屏幕截图 #16:

屏幕截图 #17:

屏幕截图 #18:

屏幕截图 #19:

屏幕截图 #20:

屏幕截图 #21:

屏幕截图 #22:

屏幕截图 #23:

屏幕截图 #24:

屏幕截图 #25:

屏幕截图 #26:

【讨论】:

  • 上帝的圣母。我从未见过如此详细、如此仔细地提出的答案。你太棒了!
  • 也许您应该将他的帖子标记为您问题的答案。
【解决方案2】:

如果数据已排序并且 Account# 是整数,我会:

将电子邮件插入表格(添加自动增量列,这是最佳实践)。

1  101    alpha@foo.com
2  101    bravo@foo.com
3  101    charlie@yay.com
etc.

然后我会将其他记录插入到父表中。

  • 使用 Account# 作为主键
  • 省略电子邮件地址
  • 跳过重复项(如果数据 已排序)。

如果您有外键关系设置,则需要先执行第二步(以避免出现任何孤立记录)。

我的两分钱:我不知道您的要求是什么,但它似乎有点过度规范化。如果对电子邮件地址的数量有一个小的限制,我会考虑在主表中添加几个电子邮件列...为了速度和简单性。

【讨论】:

  • 由于我对 SSIS 不熟悉,我已经调整了我的问题,以特别强调以 SSIS 语言表达的解决方案。也就是说,听起来像“创建一个平面文件源容器,并将其挂钩到 foreach 循环容器,然后将数据流任务添加到 foreach 循环容器。等等。”
猜你喜欢
  • 2011-01-07
  • 1970-01-01
  • 1970-01-01
  • 2011-08-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-09-18
  • 1970-01-01
相关资源
最近更新 更多