2010-12-08 5 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 코드에서 복잡성을 제거하고 데이터베이스에 액세스 할 수 있는지 몇 가지 추가 검사를 수행합니다. –