【问题标题】:SSIS Expression to handle NULLs in multiple columns用于处理多列中的 NULL 的 SSIS 表达式
【发布时间】:2020-08-06 17:14:11
【问题描述】:

我有一个 OLE DB 源,它有一些空值,它有 50 列,我正在尝试将具有 NULLs 的行提取到错误数据目标,条件拆分的表达式是

ISNULL([StudentName]) == TRUE

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

【问题讨论】:

    标签: sql-server ssis etl oledb conditional-split


    【解决方案1】:

    信不信由你,自从你发布它以来,这一直让我感到困惑。

    我还没有想出一种方法来实现 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 数据类型中的列,这是在使用转换的脚本组件时必须使用的。我需要实际使用脚本组件源并将数据加载到数据表中才能访问 Columns 属性。

    【讨论】:

      【解决方案2】:

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

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

      【讨论】:

        【解决方案3】:

        当然还有其他方法,为什么不创建一个脚本来为您生成条件?

        如果 50 列不在特定表中,只需创建一个包含所有您需要的列的 tmp 表(select ..... into #tmp from ...)

        然后,生成条件。

        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 列可能会增加巨大的过堆,尤其是在您有很多行的情况下。

        更好的选择是在数据集中的每一行上放置一个标志,并过滤/重定向是否设置了“HasNullValues”。

        【讨论】:

        • 这是非常有创意的递归使用。但是,我经常发现在使用 SSIS 时,OleDB 源不太可能是 SQL Server。
        【解决方案4】:

        ALL 列是NULL 或只是ANY 列是NULL 时,不清楚您是指数据bad

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

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

        如果是 'ANY`,则可以执行以下操作:

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

        BOTH 案例中:

        您需要通过CONVERT(varchar(8000), col)将非字符串列(数字、日期等)转换为字符串

        【讨论】:

          【解决方案5】:

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

          ISNULL([StudentName])
          

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

          粘贴到 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)||
          

          只删除最后的||。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2021-05-23
            • 1970-01-01
            • 1970-01-01
            • 2020-10-12
            相关资源
            最近更新 更多