带有动态列名的sql更新

1 人关注

编辑:为简化起见,数据库名称已被修改。

我正在尝试使用一些动态的 sql 来更新一些关键生产表的 静态 副本到另一个数据库 (sql2008r2) 。这里的目的是允许在一定时期内持续传播数据(来自 "静态 "数据库),因为我们的生产数据库几乎每天都会更新。

我正在使用一个 CURSOR 来循环浏览一个包含要复制到 "静态 "数据库的对象的表。 prod 表并不经常变化,但是我想让它在某种程度上 "适应未来"(如果可能的话!)并从 INFORMATION_SCHEMA.COLUMNS 中为每个对象提取列名(而不是使用 SELECT * FROM ... .. )

  • 1) 从我在其他帖子中读到的内容来看。 EXEC() 似乎有局限性,所以我相信我需要使用 EXEC sp_executesql 但我在理解这些方面有一点困难。

  • 2) 如果可能的话,我还想排除某些表的某些列(在 "静态 "数据库中结构略有不同),作为额外的补充。

  • 这是我目前的情况。 当执行时, @colnames 返回NULL,因此 @sql 返回NULL......

    谁能指导我在哪里可以找到解决方案?
    如果有任何关于这个代码的建议或帮助,我将非常感激。

    CREATE PROCEDURE sp_UpdateRefTables 
        @debug bit = 0
    declare @proddbname varchar(50),
        @schemaname varchar(50),
        @objname varchar(150),
        @wherecond varchar(150),
        @colnames varchar(max),
        @sql varchar(max),
        @CRLF varchar(2)
    set @wherecond = NULL;
    set @CRLF = CHAR(10) + CHAR(13);
    declare ObjectCursor cursor for
    select  databasename,schemaname,objectname
    from    Prod.dbo.ObjectsToUpdate
    OPEN    ObjectCursor ;
    FETCH NEXT FROM ObjectCursor
    INTO @proddbname,@schemaname,@objname ;
    while @@FETCH_STATUS=0
    begin
    if @objname = 'TableXx'
    set @wherecond = ' AND COLUMN_NAME != ''ExcludeCol1'''
    if @objname = 'TableYy'
    set @wherecond = ' AND COLUMN_NAME != ''ExcludeCol2'''
    --extract column names for current object
    select @colnames = coalesce(@colnames + ',', '') + QUOTENAME(column_name) 
    from    Prod.INFORMATION_SCHEMA.COLUMNS
    where   TABLE_NAME = + QUOTENAME(@objname,'') + isnull(@wherecond,'')
    if @debug=1 PRINT '@colnames= ' + isnull(@colnames,'null')
    --replace all data for @objname
    --@proddbname is used as schema name in Static database
    SELECT @sql = 'TRUNCATE TABLE ' + @proddbname + '.' + @objname + '; ' + @CRLF
    SELECT @sql = @sql + 'INSERT INTO ' + @proddbname + '.' + @objname + ' ' + @CRLF
    SELECT @sql = @sql + 'SELECT ' + @colnames + ' FROM ' + @proddbname + '.' + @schemaname + '.' + @objname + '; '
    if @debug=1 PRINT '@sql= ' + isnull(@sql,'null')
    EXEC sp_executesql @sql
    FETCH NEXT FROM ObjectCursor
    INTO @proddbname,@schemaname,@objname ;
    CLOSE ObjectCursor ;
    DEALLOCATE ObjectCursor ;
    

    P.S.我读过关于sql注入的文章,但由于这是一项内部管理任务,我想我在这里是安全的!? 也希望得到这方面的任何建议。

    预先多谢。

    sql-server-2008
    dynamic-sql
    information-schema
    MarkusBee
    MarkusBee
    发布于 2012-04-17
    1 个回答
    Aaron Bertrand
    Aaron Bertrand
    发布于 2020-07-30
    已采纳
    0 人赞同

    你在对 information_schema 的查询中混合了SQL和动态SQL。另外, QUOTENAME 在where子句中没有必要,而且实际上会阻止匹配,因为SQL Server在元数据中存储了 column_name ,而不是 [column_name] 。最后,我打算把它改成 sys.columns ,因为这是 我们在SQL Server中派生元数据 的方式。试一下。

    SELECT @colnames += ',' + name 
      FROM Prod.sys.columns
      WHERE OBJECT_NAME([object_id]) = @objname