2010-12-08 99 views
1

我有一个奇怪的问题,我的嵌套游标,我不知道它是什么。SQL Server嵌套游标问题

这里是我的T-SQL代码:

declare @dbname varchar(50) 
declare @servername varchar(50) 
declare srv cursor for select servername from test.dbo.servers 
declare @str varchar(200) 

truncate table test.dbo.temp 

open srv 
fetch next from srv into @servername 
while @@fetch_status = 0 
begin 
    set @str = 'Data Source='[email protected]+';Integrated Security=SSPI' 
    declare db cursor for select name from opendatasource('SQLNCLI', @str).master.dbo.sysdatabases 
    open db 
    fetch next from db into @dbname 
    while @@fetch_status = 0 
    begin 
     insert test.dbo.temp (dbname, servername) values (@dbname, @servername) 
     fetch next from db into @dbname 
    end 
    fetch next from srv into @servername 
    close db 
    deallocate db 
end 
close srv 
deallocate srv 

它给了我一个错误信息:

附近有语法错误@str“。 [SQLSTATE 42000](Error 102)

看起来问题在于将变量作为参数赋予opendatasource函数。但为什么?以及如何避免这个问题?

+4

*嵌套游标*:这是你的问题就在那里! – 2010-12-08 12:27:43

+2

@marc_s我认为嵌套游标是做OP的唯一可行的方法(循环遍历服务器集合中的所有数据库,其名称包含在表中) – 2010-12-08 14:06:46

回答

3

你是正确的,变量不能传递给OPENDATASOURCE。相反,你必须使用文字。尽管我们不鼓励使用动态SQL,但有些情况是不可避免的。试试这样的:

declare @dbname varchar(50) 
declare @servername varchar(50) 
declare srv cursor for select servername from test.dbo.servers 
declare @str varchar(200) 
declare @sql nvarchar(MAX) 

truncate table test.dbo.temp 

open srv 
fetch next from srv into @servername 
while @@fetch_status = 0 
begin 
    SET @sql = N' 
    declare db cursor for select name from opendatasource(''SQLNCLI'', ''Data Source='[email protected]+';Integrated Security=SSPI'').master.dbo.sysdatabases 
    open db 
    fetch next from db into @dbname 
    while @@fetch_status = 0 
    begin 
     insert test.dbo.temp (dbname, servername) values (@dbname, @servername) 
     fetch next from db into @dbname 
    end 
    close db 
    deallocate db 
    ' 
    EXEC sp_executesql 
    @sql, 
    N'@dbname  varchar(50), 
     @servername varchar(50)', 
    @dbname, 
    @servername 

    fetch next from srv into @servername 
end 
close srv 
deallocate srv 
+1

非常感谢!我没有这样想过! :) 它真的帮助! – stee1rat 2010-12-10 09:40:28

2

如果你需要使用嵌套游标,你做错了什么。使用游标而不是其他一些基于集合的操作的原因很少,并且在游标中使用游标就像是最终的SQL Server反模式。

对于你的内心光标,你可以改变它使用无证sp_msforeachdb功能(这显然创建了一个光标幕后)

open srv 
fetch next from srv into @servername 
while @@fetch_status = 0 
begin 
EXEC sp_msforeachdb ' 
Data Source='[email protected]+';Integrated Security=SSPI 
insert test.dbo.temp (dbname, servername) values (?, @Servername)' 
fetch next from srv into @servername 
end 
close srv 
deallocate srv 

您可能需要封闭?用单引号和逃避他们,如:

EXEC sp_msforeachdb 'insert test.dbo.temp (dbname, servername) values (''?'', @Servername)