使用保持外键关系的SSIS加载多个表
我试图使用SSIS将数据从单个文件(具有百万条记录)加载到SQL Server上的多个表中,同时保持文件中定义的关系。
为了更好地阐述一个例子,我们假设我正在尝试加载一个文件,其中包含员工姓名,他们在过去占据的办公地点以及他们的职位标题历史记录,并由选项卡分隔。
文件:
EmployeeName<tab>OfficeHistory<tab>JobLevelHistory
John Smith<tab>501<tab>Engineer
John Smith<tab>601<tab>Senior Engineer
John Smith<tab>701<tab>Manager
Alex Button<tab>601<tab>Senior Assistant
Alex Button<tab>454<tab>Manager
如果我的Office数据库架构具有下列表格:
Employee (nId, name)
Office (nId, number)
JobTitle (nId, titleName)
Employee2Office (nEmpID, nOfficeId)
Employee2JobTitle (nEmpId, nJobTitleID)
我如何使用SSIS将文件加载到上面的架构中,为Employee,Office和JobTitle自动生成ID并维护员工和办公室之间以及员工和职位的关系?
所以在这种情况下。 表格应如下所示:
Employee
1 John Smith
2 Alex Button
Office
1 501
2 601
3 701
4 454
JobTitle
1 Engineer
2 Senior Engineer
3 Manager
4 Senior Assistant
Employee2Office
1 1
1 2
1 3
2 2
2 4
Employee2JobTitle
1 1
1 2
1 3
2 4
2 3
我是SSIS的新手,并没有在执行数据流任务时使用自动生成的ID和建立外键关系。 任何指针将不胜感激。
谢谢!
一个有趣的问题。 这里是我将如何做(Sql Server 2005)。 (我假设这是一个月度工作,而不只是一次,所以我添加了可重复性代码。)
输出进入脚本组件,其中包含平面文件中的三列作为输入,将三个表变量导入到脚本中,脚本组件中的五个输出分别具有相同的排除组编号和标记为同步输出的输入七个添加到输出中的新列(emp为每个输出3个,其中2个为工作,2个为办公室),并使用以下代码(必须添加System.xml.dll引用才能完成此操作工作。):
Imports System
Imports System.Data
Imports System.Math
Imports Microsoft.SqlServer.Dts.Pipeline.Wrapper
Imports Microsoft.SqlServer.Dts.Runtime.Wrapper
Imports System.Collections
Imports System.Data.OleDb
Public Class ScriptMain
Inherits UserComponent
Private da As New OleDbDataAdapter
Private emp As New DataTable
Private emph As New Hashtable()
Private job As New DataTable
Private jobh As New Hashtable()
Private off As New DataTable
Private offh As New Hashtable()
Private maxempid As Integer
Private maxjobid As Integer
Private maxoffid As Integer
Public Overrides Sub PreExecute()
maxempid = 0
maxjobid = 0
maxoffid = 0
da.Fill(emp, Me.Variables.EmpTab)
For Each dr As DataRow In emp.Rows
emph.Add(dr.Item("Name"), dr.Item("nID"))
If (CInt(dr.Item("nID").ToString) > maxempid) Then
maxempid = CInt(dr.Item("nID").ToString)
End If
Next
da.Fill(job, Me.Variables.JobTab)
For Each dr As DataRow In job.Rows
jobh.Add(dr.Item("titleName"), dr.Item("nID"))
If (CInt(dr.Item("nID").ToString) > maxempid) Then
maxjobid = CInt(dr.Item("nID").ToString)
End If
Next
da.Fill(off, Me.Variables.OffTab)
For Each dr As DataRow In off.Rows
offh.Add(dr.Item("number"), dr.Item("nID"))
If (CInt(dr.Item("nID").ToString) > maxempid) Then
maxoffid = CInt(dr.Item("nID").ToString)
End If
Next
emp.Dispose()
job.Dispose()
off.Dispose()
da.Dispose()
MyBase.PreExecute()
End Sub
Public Overrides Sub Input0_ProcessInputRow(ByVal Row As Input0Buffer)
If Not emph.ContainsKey(Row.EmployeeName) Then
maxempid += 1
emph.Add(Row.EmployeeName, maxempid)
Row.EmpId = maxempid
Row.Emp2Id = maxempid
Row.Emp3Id = maxempid
Row.DirectRowToEmployee()
Else
Row.EmpId = CInt(emph.Item(Row.EmployeeName).ToString)
Row.Emp2Id = CInt(emph.Item(Row.EmployeeName).ToString)
Row.Emp3Id = CInt(emph.Item(Row.EmployeeName).ToString)
End If
If Not jobh.ContainsKey(Row.JobLevelHistory) Then
maxjobid += 1
jobh.Add(Row.JobLevelHistory, maxjobid)
Row.JobId = maxjobid
Row.Job2Id = maxjobid
Row.DirectRowToJobTitle()
Else
Row.JobId = CInt(jobh.Item(Row.JobLevelHistory).ToString)
Row.Job2Id = CInt(jobh.Item(Row.JobLevelHistory).ToString)
End If
If Not offh.ContainsKey(Row.OfficeHistory) Then
maxoffid += 1
offh.Add(Row.OfficeHistory, maxoffid)
Row.OffId = maxoffid
Row.Off2Id = maxoffid
Row.DirectRowToOfficeNumber()
Else
Row.OffId = CInt(offh.Item(Row.OfficeHistory).ToString)
Row.Off2Id = CInt(offh.Item(Row.OfficeHistory).ToString)
End If
Row.DirectRowToEmp2Job()
Row.DirectRowToEmp2Off()
End Sub
End Class
这个脚本的结果(该脚本为输入数据中的新值生成id,它通过将现有表加载到脚本的预先执行部分中的哈希表中,然后通过检查名称的存在并根据该名称增加maxid并将其添加到散列,如果它添加到散列,它还将该行添加到适当的(emp,job或off)输出,或从每个行的散列中检索maxid)。上面的状态将被写入剩下的两个输出(emp2job和emp2off)。
如果您确定您希望加载的数据的引用完整性正常,则可以在脚本任务中禁用外键约束,然后在并行数据加载的情况下执行数据流,并在数据加载完成后再次启用约束。 如果数据不对,操作将失败。 你将不得不设计回滚或清理策略。
另一种选择是以串行方式加载数据,从主表开始并在子表上完成。 我认为这是'更安全'的选择,因为它不会将您的数据完整性暴露给可能在ETL加载时使用这些表的其他用户。 我更喜欢这个选项。
这是如何 - 仅用文字解释有点困难,但我会试试看:
使用标识列在数据库中定义员工,办公室和职位表,以便自动生成ID。
定义没有多对多表(不需要或不需要标识)
在您的SSIS数据流中,您必须在几次传递中完成此操作,以便首先在数据库中建立ID,然后返回并插入多对多行。
制作一个数据流:
在第一个数据流之后,添加第二个数据流。 这将填充多对多关系行
上一篇: Loading Multiple Tables using SSIS keeping foreign key relationships