微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如果数据存在于数据库中,则 SSIS 失败

如何解决如果数据存在于数据库中,则 SSIS 失败

我有一个带有索引唯一 ID 的 sql 数据库。 我正在使用 SSIS 将数据从 Excel 导入 sql 数据库。如果该 ID 存在于数据库中,当我的 sql Server 数据库中存在重复项时,我会收到错误无法在具有唯一索引的对象中插入重复的键行,我希望 SSIS 跳过导入该行,如果行(它的 ID)存在于数据库中,则跳转到下一个。我该如何解决这个问题?

解决方法

您可以使用:

  1. 使用条件拆分转换进行聚合转换

将聚合转换带到数据流窗格并将您的 Excel 文件源连接到聚合转换。您需要将它们分组并计数。

将条件拆分转换拖到数据流窗格并将聚合转换连接到它。

通过使用条件拆分,您会将重复记录重定向到输出,您可以将它们写入表/文件。

使用 Int 将 [Count All] 转换为 Cast Function (DT_I4)

条件拆分转换将创建两个输出:

  • DuplicateRecords 用于重复记录
  • CorrectRecords 用于唯一记录

带来一个 Multicast Transformation 并将 DuplicateRecords 的输出从 Conditional Split Transformation 连接到它。

带来一个 OLE DB 目标并将 CorrectRecords 的输出从 Conditional Split Transformation 连接到它。

在它们之间放置数据查看器,以便您可以显示记录。您将实时将这些记录写入目标表/文件。

2.查找组件:

在控制流中添加一个 Lookup task 并使用它加入 Excel 文件任务。

Lookup Transformation Editor 中,指定连接管理器和缓存类型。

enter image description here

在指定如何处理没有匹配条目的行的下拉菜单中,选择以下选项:

Redirect rows to no match output

单击连接并从下拉列表中指定目标表。您在同一数据库中同时拥有源表和目标表。您也可以在此处创建单独的连接。

单击列,它会显示源表和目标表。 您想比较 Excel 文件和目标表上的 ID 列。从源中拖动 ID 列并将其移动到目标 ID 列。

从 SSIS 工具箱添加 OLE DB destination。使用 OLE DB destination 加入 Lookup 任务,它会打开以下输入-输出选择。

选择以下值:

  • 输出:查找无匹配输出:您将其附加到 OLE DB destination(SQL Server 数据库中的表)
  • 输入:OLE DB 目标输入:例如,您将其附加到平面文件目标

3. SSIS 排序结合脚本组件:

将您的源添加到数据流任务。 您需要对要用于重复数据删除的列进行排序。通常,如果您的源是数据库表,那么您应该在查询中添加一个 GROUP BY 子句,否则您应该在源之后添加一个 SORT Transformation。 在排序的源之后添加脚本组件类型转换。

编辑 Script Component 并转到 Input Columns tab 并选择要用于重复数据删除的所有列作为 ReadOnly(与用于排序的字段相同)。

转到“输入和输出”选项卡并将输出端口的名称从“输出 0”更改为“唯一”。还将 ExclusionGroup 更改为 1。

添加一个新的输出并将其命名为 Duplicate 并将 ExlusionGroup 更改为 1。要将这个新的输出端口连接到输入端口,请更改 SynchronousInputID 属性并选择输入端口。

编辑脚本并复制以下代码。此脚本使用反射来获取所有选定的列,这样您在更改输入列时就不必更改脚本。但请阅读编码注释。

// C# code
// This script automaticly compares the selected columns,but there is one 'bug':
// You have to edit and close this script again if you change input columns.
using System;
using System.Data;
using System.Reflection;                                // Added
using System.Text;                                      // Added
using Microsoft.SqlServer.Dts.Pipeline.Wrapper;
using Microsoft.SqlServer.Dts.Runtime.Wrapper;
 
[Microsoft.SqlServer.Dts.Pipeline.SSISScriptComponentEntryPointAttribute]
public class ScriptMain : UserComponent
{
    // Create a variable to store the concatenated values for the previous row
    string previousRow = "";
 
    public override void Input0_ProcessInputRow(Input0Buffer Row)
    {
        // Create a variable to store the concatenated values of current row
        StringBuilder currentRow = new StringBuilder();
 
        foreach (PropertyInfo p in Row.GetType().GetProperties())
        {
            // We can't use the _IsNull columns,so ignore them. Also ignore the new output column
            if ((p.Name.ToLower().EndsWith("_IsNull") == false) && (p.Name.Equals("Duplicate") == false))
            {
                try
                {
                    // Concatenate value as string to variable
                    currentRow.Append(p.GetValue(Row,null).ToString() + "|");
                }
                catch (ArgumentException)
                {
                    // If the value is NULL (empty) then you can't get the value of it
                    currentRow.Append("NULL|");
                }
                catch (Exception ex)
                {
                    // Raise error because something unexpected went wrong
                    bool pbCancel = false;
                    this.ComponentMetaData.FireError(0,"MarkDuplicates",p.Name + ": " + ex.Message,string.Empty,out pbCancel);
                }
            }
        }
 
        // Check if the current row and previous row are the same
        if (currentRow.ToString().Equals(previousRow))
        {
            // Redirect to duplicate output
            Row.DirectRowToDuplicate();
        }
        else
        {
            // Redirect to unique output
            Row.DirectRowToUnique();
        }
 
        // Fill previous row with current value for next check
        previousRow = currentRow.ToString();
    }
}

或 VB.Net :

' VB.Net code
' This script automaticly compares the selected columns,but there is one 'bug':
' You have to edit and close this script again if you change input columns.
 
Imports System
Imports System.Data
Imports System.Math
Imports System.Reflection                           ' Added
Imports System.Text                                 ' Added
Imports Microsoft.SqlServer.Dts.Pipeline.Wrapper
Imports Microsoft.SqlServer.Dts.Runtime.Wrapper
 
<Microsoft.SqlServer.Dts.Pipeline.SSISScriptComponentEntryPointAttribute> _
<CLSCompliant(False)> _
Public Class ScriptMain
    Inherits UserComponent
 
    ' Create a variable to store the concatenated values for the previous row
    Dim previousRow As String = ""
 
    Public Overrides Sub Input0_ProcessInputRow(ByVal Row As Input0Buffer)
        ' Create a variable to store the concatenated values of current row
        Dim currentRow As StringBuilder = New StringBuilder()
 
        Dim p As PropertyInfo
        For Each p In Row.GetType().GetProperties()
            ' We can't use the _IsNull columns,so ignore them. Also ignore the new output column
            If ((p.Name.ToLower().EndsWith("_IsNull") = False) And (p.Name.Equals("Duplicate") = False)) Then
                Try
                    ' Concatenate value as string to variable
                    currentRow.Append(p.GetValue(Row,Nothing).ToString() + "|")
                Catch ex As ArgumentException
                    ' If the value is NULL (empty) then you can't get the value of it
                    currentRow.Append("NULL|")
                Catch ex As Exception
                    ' Raise error because something unexpected went wrong
                    Dim pbCancel As Boolean
                    Me.ComponentMetaData.FireError(0,String.Empty,pbCancel)
                End Try
            End If
        Next
 
        ' Check if the current row and previous row are the same
        If (currentRow.ToString().Equals(previousRow)) Then
            ' Redirect to duplicate output
            Row.DirectRowToDuplicate()
        Else
            ' Redirect to unique output
            Row.DirectRowToUnique()
        End If
 
        ' Fill previous row with current value for next check
        previousRow = currentRow.ToString()
    End Sub
End Class

添加两个目的地并将 Data Flow Paths 连接到目的地。连接时必须选择输出端口。

不要忘记添加一些用于测试目的的数据查看器。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。