2010-12-08 19 views
1

私はネストされたカーソルに奇妙な問題があり、それが何であるか分かりません。SQL Serverのネストされたカーソルの問題

付近に正しくない構文 '@str':

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 

それは私に次のエラーメッセージを表示します。

は、ここに私のT-SQLコードです。 [SQLSTATE 42000](エラー102)

問題は、opendatasource関数のパラメータとして変数を指定しているようです。しかし、なぜ?そして、この問題を避ける方法は?

+4

*ネストされたカーソル*:それは右そこにあなたの問題です! –

+2

@marc_s私は、ネストされたカーソルは、OPがしたいことを実行する唯一の実行可能な方法だと考えています(サーバーのコレクション内のすべてのデータベースをループします、名前はテーブルに含まれています) –

答えて

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

+0

あなたは大歓迎です! –

2

ネストしたカーソルを使用する必要がある場合は、何か問題があります。他のセットベースの操作の代わりにカーソルを使用する理由はほとんどなく、カーソル内でのカーソルの使用は、究極のSQL Serverのアンチパターンと似ています。あなたが同封する必要があるかもしれません

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 

:あなたの内部のカーソルの

、あなたは(どうやら舞台裏でカーソルを作成します)文書化されていないsp_msforeachdb機能を使用するように変更することができますか?単一引用符で、それらをエスケープする、のような:

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

+2

あなたは 'sp_msforeachdb'の定義を見ていないと思いますか? (それはカーソルを使用しています!) –

+0

@Martin - lol私はそれが内部的にどのように動作したのか分かりませんでした。情報をありがとう。 – JNK

+0

@JNK - 私はまだそれを使用するための議論があるかもしれないと思う(+1)。 OPのコードからいくらかの複雑さが取り除かれ、データベースにアクセスできるかどうかの追加チェックが行われます。 –

関連する問題