我有需要导入父子表的非规范化数据(来自文件)。源数据是这样的:
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的哪些部分,部分或策略将前三列读入父表,将第4列(电子邮件)读入子表?我可以选择父键的几个选项:
我确信我已经按照增加难度的顺序列出了我的主键选项。我有兴趣知道如何做第一个和最后一个选项 - 我将推断如何实现中间选项。再次强调,我对一个明确的SSIS解决方案很感兴趣;我正在寻找使用SSIS语言的答案,而不是程序性的,技术中立的答案。
我的问题有点类似于another SO question,有一个模糊可行性的答案。我希望能给出更详细的指导。我已经知道如何通过创建一个“临时”中间步骤来解决这个问题,其中父子分离实际上是用直接SQL处理的。但是,我很好奇如果没有这种中间步骤可以做到这一点。
在我看来,这种重要性是如此常见,以至于会有一种公布的方法来处理它 - 这是SSIS擅长的一种技术。到目前为止,我还没有看到任何直接答案。
Update #1
:根据评论,我调整了示例数据,使其更加明显地非规范化。我还从“平面文件”中删除了“flat”,这样语义就不会干扰这个问题。
Update #2
:我已经放大了对使用SSIS语言的解决方案的兴趣。
答案 0 :(得分:31)
以下是加载父子数据时可以考虑的一个可能选项。此选项包含两个步骤。在第一个步骤中,读取源文件并将数据写入父表。在第二个步骤中,再次读取源文件并使用查找转换来获取父信息,以便将数据写入子表。以下示例使用问题中提供的数据。此示例是使用SSIS 2008 R2和SQL Server 2008数据库创建的。
分步流程:
创建名为Source.txt
的示例平面文件,如屏幕截图# 1 所示。
在SQL数据库中,使用 SQL Scripts 部分下提供的脚本创建两个名为dbo.Parent
和dbo.Child
的表。这两个表都有一个自动生成的标识列。
在包上,放置OLE DB connection
以连接到SQL Server,并Flat File connection
读取源文件,如屏幕截图# 2 所示。配置平面文件连接,如屏幕截图# 3 - # 9 所示。
在“控制流”标签上,放置两个Data Flow Tasks
,如屏幕截图# 10 所示。
在名为 Parent 的数据流任务中,放置一个平面文件源,排序转换和OLE DB目标,如屏幕截图# 11 所示。
配置平面文件来源,如屏幕截图# 12 和# 13 所示。我们需要阅读平面文件源。
配置排序转换,如屏幕截图# 14 所示。我们需要消除重复值,以便只将唯一记录插入父表dbo.Parent
。
配置ole db目标,如屏幕截图# 15 和# 16 所示。我们需要将数据插入父表dbo.Parent
。
在名为 Child 的数据流任务中,放置一个平面文件源,查找转换和一个OLE DB目标,如屏幕截图# 17 所示。
配置平面文件来源,如屏幕截图# 12 和# 13 所示。此配置与先前数据流任务中的平面文件源相同。
配置查找转换,如屏幕截图# 18 和# 20 所示。我们需要使用文件中存在的其他键列从表dbo.Parent
中找到父ID。这里的关键列是帐户,名称和电子邮件。如果文件碰巧有一个唯一列,您可以单独使用该列来获取父ID。
配置ole db目标,如屏幕截图# 21 和# 22 所示。我们需要将电子邮件列和父ID一起插入表dbo.Child
。
屏幕截图# 23 会在 包执行之前的表中显示数据。
屏幕截图# 24 和# 25 显示示例包执行。
屏幕截图# 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:
答案 1 :(得分:0)
如果数据已排序且Account#为整数,我会:
将电子邮件插入表格(添加自动增量列,这是最佳做法)。
1 101 alpha@foo.com
2 101 bravo@foo.com
3 101 charlie@yay.com
etc.
然后我会将其他记录插入父表。
如果您设置了外键关系,则需要先执行第二步(避免使用任何孤立记录)。
我的两分钱:我不知道你的要求是什么,但似乎有点过于规范化了。如果电子邮件地址的数量有一个小的限制,我会考虑在主表中添加几个电子邮件列...以提高速度和简单性。