Sql server 2008 使用动态列名进行sql更新
编辑:为了简单起见,对数据库名称进行了修改 我正在尝试使用一些动态sql将一些关键生产表的静态副本更新到另一个数据库(sql2008r2)。这里的目的是允许在一段时间内(从“静态”数据库)一致地传播数据,因为我们的生产数据库几乎每天都在更新 我正在使用Sql server 2008 使用动态列名进行sql更新,sql-server-2008,dynamic-sql,information-schema,Sql Server 2008,Dynamic Sql,Information Schema,编辑:为了简单起见,对数据库名称进行了修改 我正在尝试使用一些动态sql将一些关键生产表的静态副本更新到另一个数据库(sql2008r2)。这里的目的是允许在一段时间内(从“静态”数据库)一致地传播数据,因为我们的生产数据库几乎每天都在更新 我正在使用光标在一个表中循环,该表包含要复制到“静态”数据库中的对象。 prod表不会经常更改,但我想让它成为“未来的证明”(如果可能!),并从每个对象的INFORMATION\u SCHEMA.columns中提取列名称(而不是使用SELECT*from…
光标
在一个表中循环,该表包含要复制到“静态”数据库中的对象。
prod
表不会经常更改,但我想让它成为“未来的证明”(如果可能!),并从每个对象的INFORMATION\u 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 ;
另外,我已经读过关于sql注入的内容,但由于这是一项内部管理任务,我猜我在这里是安全的!?在此方面的任何建议也将不胜感激
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 ;
非常感谢。在对
信息\u模式的查询中,您混合了SQL和动态SQL。此外,where子句中不需要QUOTENAME
,实际上会阻止匹配,因为SQL Server在元数据中存储column\u name
,而不是[column\u name]
。最后,我将把它改为sys.columns
,因为这就是方法。尝试:
选择@colnames+=','+name
从Prod.sys.columns
其中OBJECT_NAME([OBJECT_id])=@objname
当@objname='TableXx'然后是'ExcludeCol1'ELSE'结束时,命名大小写
当@objname='TableYy'然后'ExcludeCol2'ELSE'结束时,命名CASE;
设置@colnames=STUFF(@colnames,1,1,,);
在对信息\u模式的查询中,SQL和动态SQL混合使用。此外,where子句中不需要QUOTENAME
,实际上会阻止匹配,因为SQL Server在元数据中存储column\u name
,而不是[column\u name]
。最后,我将把它改为sys.columns
,因为这就是方法。尝试:
选择@colnames+=','+name
从Prod.sys.columns
其中OBJECT_NAME([OBJECT_id])=@objname
当@objname='TableXx'然后是'ExcludeCol1'ELSE'结束时,命名大小写
当@objname='TableYy'然后'ExcludeCol2'ELSE'结束时,命名CASE;
设置@colnames=STUFF(@colnames,1,1,,);
非常感谢Aaron,我将尝试一下。我认为INFORMATION_SCHEMA.Columns最好,但会根据您的答案修改为sys.Columns。我还知道我必须将IFs更改为CASE语句,但我不知道的内容并将查找此内容:)内容只是删除了前面的,
-这比在查询中执行所有的合并
连接内容要容易得多。您的答案非常有效。非常感谢。我想我把问题复杂化了。不过我个人更喜欢COALESCE——我觉得它更优雅一点,在这个例子中,它减轻了对STUFF语句的需要。不过,我可以看到其他用途的东西,所以请记住这一点。:)好吧,我想优雅是很主观的。非常感谢亚伦,我来试试。我认为INFORMATION_SCHEMA.Columns最好,但会根据您的答案修改为sys.Columns。我还知道我必须将IFs更改为CASE语句,但我不知道的内容并将查找此内容:)内容只是删除了前面的,
-这比在查询中执行所有的合并
连接内容要容易得多。您的答案非常有效。非常感谢。我想我把问题复杂化了。不过我个人更喜欢COALESCE——我觉得它更优雅一点,在这个例子中,它减轻了对STUFF语句的需要。不过,我可以看到其他用途的东西,所以请记住这一点。:)好吧,我想优雅是很主观的。