1

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

これが私の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='+@servername+';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](エラー102)

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

4

2 に答える 2

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='+@servername+';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
于 2010-12-08T12:19:23.620 に答える
1

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

sp_msforeachdb内側のカーソルについては、文書化されていない関数(明らかに舞台裏でカーソルを作成する)を使用するように変更できます。

open srv
fetch next from srv into @servername
while @@fetch_status = 0   
begin
 EXEC sp_msforeachdb '
 Data Source='+@servername+';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)

于 2010-12-08T13:38:20.780 に答える