用于处理多列中的 NULL 的 SSIS 表达式

SSIS Expression to handle NULLs in multiple columns

我有一个包含一些空值的 OLE DB 源,它有 50 列,我正在尝试将具有 NULLs 的行提取到 Bad data destination,即我用于条件拆分的表达式是

ISNULL([StudentName]) == TRUE

但这意味着我必须对我拥有的所有专栏重复它,我想知道是否有另一种方法来处理这个问题。特别是因为我有多个表要处理。 谢谢

信不信由你,自从你发布以来,我一直很困惑。

我还没有想出一种方法来执行 SSIS,但这里有一个使用脚本组件源的可能解决方案。这将找到与至少有一个空列的行关联的所有键。

    DataTable dt = new DataTable();

    string sql = "Enter your extract SQL here";
    using(OleDbConnection conn = new OleDbConnection("Data Source=XXXXXXXXX;Initial Catalog=YYYYY;Provider=SQLNCLI11.1;Integrated Security=SSPI;Auto Translate=False;"))
    {
        using (OleDbCommand cmd = new OleDbCommand(sql,conn))
        {
            cmd.CommandType = CommandType.Text;
            conn.Open();
            dt.Load(cmd.ExecuteReader());
        }
    }

    foreach (DataRow row in dt.Rows)
    {
        foreach (DataColumn col in dt.Columns)
        {
            if (row[col] == DBNull.Value)
            {
                Output0Buffer.AddRow();
                Output0Buffer.NullRowKey = row.Field<int>(0); //This is the 0 based index of the key in the data
                break;
            }
        }
    }

我 运行 遇到的问题是尝试在 Output0Buffer 数据类型中使用列,这是在使用转换的脚本组件时必须使用的数据类型。我需要实际使用脚本组件源并将数据加载到数据 table 中才能访问列 属性.

最简单的解决方案(我不确定是否从性能角度推荐它) 是在 OLE DB 源中使用 SQL 命令,您应该在其中添加一个新列,它是所有列的串联。然后,您应该在条件拆分中使用此列,而不是提及所有列。例如:

SELECT *, [Column1] + [Column2] + [Column3] as [CheckColumn]
FROM [Table]

不清楚当 ALL 列是 NULL 时数据 bad 还是只是 ANY 列是 NULL.

如果是ALL,那么你可以这样做:

COALESCE(col1, col2, col3, .....) IS NULL

如果是“ANY”,那么您可以执行以下操作:

(col1 + col2 + col3 + .....) IS NULL

BOTH个案例中:

您需要通过 CONVERT(varchar(8000), col)

将 non-string 列(数字、日期等)转换为字符串

这是一个完全不同的解决方案,使用您已经形成的条件拆分:

ISNULL([StudentName])

您可以通过粘贴列列表在 Excel 中构建 OR 测试(我从数据流路径上的元数据中获取)。我通常使用这种技术来构建目标 table.

粘贴到 excel 并将列名放入 Col A.

将此公式输入 ColB:

="ISNULL("&A1&")||"

直接在B2中输入这个公式:

=B1&"ISNULL("&A2&")||"

这应该会在 B2 中产生这样的结果:

ISNULL(Col1)||ISNULL(Col2)||

现在将 B2 拖放到列表底部(在您的情况下为 B50)。

B50 现在将保留您的条件拆分的最终公式:

ISNULL(Col1)||ISNULL(Col2)||ISNULL(Col3)||ISNULL(Col4)||ISNULL(Col5)||ISNULL(Col6)||ISNULL(Col7)||ISNULL(Col8)||ISNULL(Col9)||ISNULL(Col10)||ISNULL(Col11)||ISNULL(Col12)||ISNULL(Col13)||ISNULL(Col14)||ISNULL(Col15)||ISNULL(Col16)||ISNULL(Col17)||ISNULL(Col18)||ISNULL(Col19)||ISNULL(Col20)||ISNULL(Col21)||ISNULL(Col22)||ISNULL(Col23)||ISNULL(Col24)||ISNULL(Col25)||ISNULL(Col26)||ISNULL(Col27)||ISNULL(Col28)||ISNULL(Col29)||ISNULL(Col30)||ISNULL(Col31)||ISNULL(Col32)||ISNULL(Col33)||ISNULL(Col34)||ISNULL(Col35)||ISNULL(Col36)||ISNULL(Col37)||ISNULL(Col38)||ISNULL(Col39)||ISNULL(Col40)||ISNULL(Col41)||ISNULL(Col42)||ISNULL(Col43)||ISNULL(Col44)||ISNULL(Col45)||ISNULL(Col46)||ISNULL(Col47)||ISNULL(Col48)||ISNULL(Col49)||ISNULL(Col50)||

只删除最后的||。

当然还有另一种方法,为什么不创建一个将为您生成条件的脚本呢?

如果这 50 列不在特定的 table 中,只需创建一个包含您需要的所有列的 tmp table(select ..... 进入 #tmp 来自.... )

然后,生成条件。

declare @schema sysname = 'Purchasing'
declare @table sysname = 'PurchaseOrders'
        
;with cols as (
        select  convert(varchar(max), 'ISNULL(' + QUOTENAME(column_name) + ') == TRUE') as col, TABLE_SCHEMA, TABLE_NAME, ordinal_position 
        from INFORMATION_SCHEMA.COLUMNS 
        where TABLE_SCHEMA = @schema and TABLE_NAME = @table and ORDINAL_POSITION = 1
        union all
        select CONVERT (varchar(max) , cl.col + ' || ISNULL(' + QUOTENAME(column_name) + ') == TRUE') as col, c.TABLE_SCHEMA, c.TABLE_NAME, c.ordinal_position 
        from INFORMATION_SCHEMA.COLUMNS c
        inner join cols cl on cl.TABLE_SCHEMA = c.TABLE_SCHEMA and cl.TABLE_NAME = c.TABLE_NAME and c.ORDINAL_POSITION = cl.ORDINAL_POSITION + 1
    )
    select '= ' + cols.col 
    from cols
    where ORDINAL_POSITION = (select MAX(ordinal_position) from cols)

使用 WideWorldImporters 数据库,这将产生条件,删除不需要的内容。

= ISNULL([PurchaseOrderID]) == TRUE || ISNULL([SupplierID]) == TRUE || ISNULL([OrderDate]) == TRUE || ISNULL([DeliveryMethodID]) == TRUE || ISNULL([ContactPersonID]) == TRUE || ISNULL([ExpectedDeliveryDate]) == TRUE || ISNULL([SupplierReference]) == TRUE || ISNULL([IsOrderFinalized]) == TRUE || ISNULL([Comments]) == TRUE || ISNULL([InternalComments]) == TRUE || ISNULL([LastEditedBy]) == TRUE || ISNULL([LastEditedWhen]) == TRUE

但请注意,无论您选择哪种方法(我的方法或使用 Excel 生成条件),在 SSIS 中测试 50 列都可能会增加巨大的过载,尤其是当您有很多行时。

更好的选择是在数据集中的每一行上放置一个标志,filter/redirect是否设置了“HasNullValues”。