【问题标题】:SSIS Multiple Unknow Column UpdatesSSIS 多个未知列更新
【发布时间】:2013-08-26 12:12:12
【问题描述】:

我想知道在此之前是否有人遇到过类似的情况,可以为我指明正确的方向..?我要补充一点,这有点令人沮丧,因为有人用包含单词“NULL”的文本字符串替换了 NULL 值 - 我需要删除它。

我有 6 个相当大的表,超过 250 多个列,每个表中超过 100 万条记录,我需要更新 NULL 单词连续出现的列,并将其替换为适当的 NULL 值 - 问题是我不知道它出现在哪一列。

首先,我有一些代码会列出每一列的值的计数以及任何看起来比预期的计数低的内容,我将运行 SQL 查询以确定该列是否包含字符串 'NULL' 并使用以下代码,将其替换为 NULL。

declare @tablename sysname
declare @ColName nvarchar(500)
declare @sql nvarchar(1000)
declare @sqlUpdate nvarchar(1000)
declare @ParmDefinition nvarchar(1000)

set @tablename = N'Table_Name'  
Set @ColName = N'Column_Name'
set @ParmDefinition = N'@ColName nvarchar OUTPUT';

set @sql= 'Select ' + @ColName + ', Count(' + @ColName + ') from ' + @tablename + ' group by ' + @ColName + ''
Set @sqlUpdate = 'Update ' + @tablename + ' SET ' + @ColName + ' = NULL WHERE '+ @ColName + ' = ''NULL'''

print @sql
print @sqlUpdate 

EXECUTE sp_executesql @sql, @ParmDefinition, @ColName=@ColName OUTPUT;
EXECUTE sp_executesql @sqlUpdate, @ParmDefinition, @ColName=@ColName OUTPUT;

我尝试使用 SSIS 是遍历每一列,

Select Column_Name from Table_Name where Column_Name = 'NULL'

运行适当的查询,并执行更新。

到目前为止,我可以从 Information.Schema 中提取列名并从相应的表中获取记录数,但是在运行实际的 UPDATE 语句时 (如上,sqlUpdate ) - 似乎没有一个组件对查询的动态措辞感到满意。

我正在使用 条件拆分 来确定如果有记录(可能不正确)去哪里,并且我已尝试 OLE DB 命令 进行更新.

简而言之,我想知道 SSIS 是否是这项工作的最佳工具,还是我找错地方了!

我使用的是 SSIS 2005,它可能有一些我还不知道的限制!

任何指导将不胜感激。

谢谢,

乔恩

【问题讨论】:

    标签: sql sql-server sql-server-2005 ssis


    【解决方案1】:

    原理基本上是合理的,但我会忽略 SSIS,并直接针对 SQL Server 使用 SSMS 并在那里构建循环逻辑,可能使用游标。

    我不确定您是否需要先检查潜在值的计数 - 您不妨应用更新并接受有时它不会更新任何行 - 然后过滤将不会重复。

    类似

    declare columns cursor local read_only for
    select 
        c.TABLE_CATALOG,
        c.TABLE_SCHEMA,
        c.TABLE_NAME,
        c.COLUMN_NAME
    from INFORMATION_SCHEMA.COLUMNS c
        inner join INFORMATION_SCHEMA.TABLES t
            on c.TABLE_CATALOG = t.TABLE_CATALOG
            and c.TABLE_SCHEMA = t.TABLE_SCHEMA
            and c.TABLE_NAME = c.TABLE_NAME
    where c.DATA_TYPE like '%varchar%'  
    
    open columns    
    declare @catalog varchar(100), @schema varchar(100), @table varchar(100), @column varchar(100)
    
    fetch from columns into @catalog, @schema, @table, @column
    
    while @@FETCH_STATUS= 0
    begin
         -- construct update here and execute it.       
        select @catalog, @schema, @table, @column
        fetch next from columns into @catalog, @schema, @table, @column
    end
    
    close columns
    deallocate columns
    

    您还可以考虑一次性将所有更新应用到表中,删除过滤器并使用nullif,具体取决于不良数据的密度。

    例如:

     update table
     set
        col1 = nullif(col1, 'null'),
        col2 = nullif(col2, 'null'),
        ...
    

    【讨论】:

    • 是的,检查计数只会使需要完成的表和/或索引扫描量翻倍,因为更新通常会进行全面扫描...
    【解决方案2】:

    SSIS 不是您的最佳选择。从概念上讲,您正在执行更新,很多更新。 SSIS 可以真正快速插入。更新,是在痛苦的行基础上连续触发的。

    在基于 SQL 的方法中,您将触发 1000 条更新语句来修复所有问题。在基于 SSIS 的场景中,使用带有 OLE DB 命令的数据流,您看到的是 1000 * 1000000。

    我会自己跳过光标。这是使用游标的可接受时间,但如果您的表像听起来一样充满“NULL”,那么假设您正在更新每一行并修复给定记录中的所有字段,而不是回到同一行每件事都需要修复。

    【讨论】:

    • 我只是建议使用游标来构建表/列列表,而不是自己进行更新。
    • 我感觉 SSIS 行不通,但我必须向自己证明这一点,并在此过程中找到了一些有用的指南。目前,我已经满足于更新上述代码 sn-p 中的行,我将找到一种循环遍历 SSMS 中的列的方法。我有一个类似的定位列的游标语句,我将其用作 SSIS 列标准的基础,因此我将尝试将其用于不同的解决方案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-03-29
    • 2021-09-27
    • 1970-01-01
    • 2016-12-26
    • 1970-01-01
    相关资源
    最近更新 更多