I have a strange problem with my nested cursors and I have no idea what it's all about.
Here's my T-SQL code:
declare @dbname varchar(50)
dec开发者_如何学Clare @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
It gives me next error message:
Incorrect syntax near '@str'. [SQLSTATE 42000] (Error 102)
Looks like the problem is in giving the variable as a parameter to opendatasource function. But why? And how to avoid this problem?
You are correct that variables cannot be passed to OPENDATASOURCE
. Instead You must use a literal instead. As much as we discourage using dynamic SQL, there are some cases that it is unavoidable. Try something like this:
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
If you need to use nested cursors, you are doing something wrong. There are very few reasons to use a cursor instead of some other set-based operation, and using a cursor within a cursor is like the ultimate SQL Server anti-pattern.
For your inner cursor, you could change it to use the undocumented sp_msforeachdb
function (which apparently creates a cursor behind the scenes):
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
You may need to enclose the ? in single quotes and escape them, like:
EXEC sp_msforeachdb 'insert test.dbo.temp (dbname, servername) values (''?'', @Servername)
精彩评论