编辑:为简单起见,修改了数据库名称
我正在尝试使用一些动态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注入的内容,但由于这是一个内部管理任务,我猜我在这里很安全!?对此的任何建议也表示赞赏。
提前多多感谢。答案 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, '');