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

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

对于您的内部光标,您可以将其更改为使用未记录的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 回答