带动态列名的sql更新

时间:2012-04-17 11:34:21

标签: sql-server-2008 dynamic-sql information-schema

编辑:为简单起见,修改了数据库名称

我正在尝试使用一些动态sql将某些关键生产表的 static 副本更新到另一个数据库(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
AS
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 ;

end
CLOSE ObjectCursor ;
DEALLOCATE ObjectCursor ;

P.S。我已经阅读了关于sql注入的内容,但由于这是一个内部管理任务,我猜我在这里很安全!?对此的任何建议也表示赞赏。

提前多多感谢。

1 个答案:

答案 0 :(得分:1)

information_schema的查询中混合使用SQL和动态SQL。此外,在where子句中不需要QUOTENAME,并且实际上会阻止匹配,因为SQL Server在元数据中存储column_name,而不是[column_name]。最后,我要将其更改为sys.columns,因为这是we should be deriving metadata in SQL Server的方式。尝试:

SELECT  @colnames += ',' + name 
  FROM Prod.sys.columns
  WHERE OBJECT_NAME([object_id]) = @objname
  AND name <> CASE WHEN @objname = 'TableXx' THEN 'ExcludeCol1' ELSE '' END
  AND name <> CASE WHEN @objname = 'TableYy' THEN 'ExcludeCol2' ELSE '' END;

SET @colnames = STUFF(@colnames, 1, 1, '');