具有表变量的动态查询可遍历所有表以在数据库中进行更新

时间:2019-03-07 17:13:34

标签: tsql

我正在处理SQL查询以更新数据库中的表和列的列表。欢迎任何建议。

我正在使用information_schema.tables和information_schema.columns,查找表和一个表变量。但是,我在更新时遇到问题。

我从联接开始,以确保我将正确的表和所需的列与查找表匹配。

如果table.column,我需要遍历并更新与对象名匹配的表。

我曾经尝试使用游标,但是做了一些研究,认为表变量可能对优化和性能更好。 我声明了变量并创建了一个表变量,但它仍未更新。创建并填充表变量后,我从下面的查询开始。

我用游标和表变量尝试了不同的方法,但是我无法正确完成更新。

'Select l.objectname, l.fieldname, l.newpvalue, l.oldpvalue from lookup_table 1 inner join information_schema.tables t
                 on l.objectname = t.table_name
                inner join information_schema.columns c
                  on l.fieldname = c.column_name and l.objectname 
                                 = c.table_name'

这是我要参数化的新更新

SELECT 'UPDATE' + I.TABLE_NAME + 'SET C.COLUMN_NAME = 
                                        CASE 
                                            WHEN TP.[listValue] = TP.[OldValue]
                                            WHEN TP.[listValue] != TP.[OldValue] 
                                                        THEN SET TP.NOTES = C.COLUMN_NAME '-' TP.[OldValue]
                                                        AND SET C.COLUMN_NAME = NULL
                                        END
        FROM 
                INFORMATION_SCHEMA.TABLES I INNER JOIN [dbo].[tpRef] tp
                                    ON I.TABLE_NAME = tp.ObjectName
                                INNER JOIN INFORMATION_SCHEMA.COLUMNS C
                                    ON tp.[FieldName] = C.COLUMN_NAME
                                        AND tp.[ObjectName] = C.TABLE_NAME
                                LEFT JOIN INFORMATION_SCHEMA.COLUMNS C2
                                    ON tp.[FieldName] = C2.COLUMN_NAME
                                    AND C2.COLUMN_NAME = 'NOTES'
        WHERE TABLE_TYPE = 'base table'
                        AND tp.ObjectName = 'table name'
                        AND tp.FieldName = 'table field'
                        AND tp.[listValue] = 'List' 

2 个答案:

答案 0 :(得分:0)

我试图使用表变量,但您是否要同时使用表变量和游标?

我跑下面的东西要花很长时间。

----更新表并找到列

SELECT @STRUPDSQL =
         'UPDATE' + 'I.TABLE_NAME' + 'SET C.COLUMN_NAME = 
                                        CASE 
                                            WHEN TP.[PicklistValue] = TP.[OldValue]
                                            WHEN TP.[PicklistValue] != TP.[OldValue] 
                                                        THEN SET TP.NOTES = C.COLUMN_NAME - TP.[OldValue]
                                                        AND SET C.COLUMN_NAME = NULL
                                        END
        FROM 
                INFORMATION_SCHEMA.TABLES I INNER JOIN @TBLS T
                                            ON I.TABLE_NAME = T.v_TABLENAME

        WHERE T.v_TABLENAME =@l_TBLNM   AND T.v_COLUMNNAME =@l_COLNNM                   

'
    SET @I = @I + 1
    END

我可以使用它,但是要更新的值被读取为列名,而不是列数据值。

IF quotename(@COLNAME)不为空

        BEGIN
            SET @SQL = 'UPDATE ' + quotename(@TABLENAME) + ' SET ' + quotename(@COLNAME) + ' = ' +'"' + @TVALUE + '"' + ' ' + 'WHERE ' + quotename(@COLNAME) + '= AccountSource'
        END

答案 1 :(得分:0)

不是有效的游标,需要查询来填充所需的列以填充变量。

declare 
     @table_name varchar(128) 
    ,@schema_name varchar(128) -- dbo is the default schema, if custom make sure query returns the correct schema
    ,@update_column varchar(128) 
    ,@update_data varchar(1024)
    ,@where_column varchar(128)
    ,@where_data varchar(1024)
    ,@s varchar(max);
declare x cursor local fast_forward 
for
/*
 insert your query returning desired values to be looped through.
 */
select 1,2,3,4,5,6 --6 variables to populate. delete this line when you get your query written above :)
open x;
fetch next from x into @table_name,@update_column,@schema_name,@update_data,@where_column,@where_data;

while @@fetch_status = 0
    begin
        set @s = '
            update ' + quotename(@schema_name) + '.' + quotename(@table_name) + ' 
            set  ' + quotename(@update_column) + ' = ''' + @update_data + ''' where ' + quotename(@where_column) + ' = ''' + @where_data + ''';
            '
        begin try
            --to execute it, you can use exec()
            exec(@s); 
            --to print out the string so you can read and or copy/paste to text execution use print()
            print(@s);
            /* 
                I would recommend print(@s); until you have all your bugs worked out.
                process the updates manually from the printed statements to verify syntax correctness and results
             */
        end try
        begin catch
            print error_message()
        end catch;
        -- this list of variables must match the first "fetch next" and all be declared and returned in the "for" query of the cursor.
        -- those that are not must be set inside the cursor by queries, calculations or hardcoded.
        fetch next from x into @table_name,@update_column,@schema_name,@update_data,@where_column,@where_data;
    end

close x;
deallocate x;

使用的光标是
Fast_forward(SO答案)=(只读和正向) Local(光标性能明细)=作用域内局部,仅在作用域内有效。

我仍然无法让自己使用information_schema视图...