2010-12-08 98 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)