문제

저장 프로 시저에서 만든 동적 SQL 문이 있습니다. 커서를 사용하여 결과를 반복해야합니다. 올바른 구문을 알아내는 데 어려움을 겪고 있습니다. 여기 내가하는 일이 있습니다.

SELECT @SQLStatement = 'SELECT userId FROM users'

DECLARE @UserId

DECLARE users_cursor CURSOR FOR
EXECUTE @SQLStatment --Fails here. Doesn't like this

OPEN users_cursor
FETCH NEXT FROM users_cursor
INTO @UserId

WHILE @@FETCH_STATUS = 0
BEGIN

EXEC asp_DoSomethingStoredProc @UserId

END
CLOSE users_cursor
DEALLOCATE users_cursor

이것을하는 올바른 방법은 무엇입니까?

도움이 되었습니까?

해결책

커서는 SELECT 문 만 수락하므로 SQL이 실제로 동적이어야하는 경우 실행중인 명령문의 커서를 선언해야합니다. 아래가 작동하려면 서버가 글로벌 커서를 사용해야합니다.

Declare @UserID varchar(100)
declare @sqlstatement nvarchar(4000)
--move declare cursor into sql to be executed
set @sqlstatement = 'Declare  users_cursor CURSOR FOR SELECT userId FROM users'

exec sp_executesql @sqlstatement


OPEN users_cursor
FETCH NEXT FROM users_cursor
INTO @UserId

WHILE @@FETCH_STATUS = 0
BEGIN
Print @UserID
EXEC asp_DoSomethingStoredProc @UserId

FETCH NEXT FROM users_cursor --have to fetch again within loop
INTO @UserId

END
CLOSE users_cursor
DEALLOCATE users_cursor

글로벌 커서 사용을 피해야하는 경우 동적 SQL의 결과를 임시 테이블에 삽입 한 다음 해당 테이블을 사용하여 커서를 채울 수도 있습니다.

Declare @UserID varchar(100)
create table #users (UserID varchar(100))

declare @sqlstatement nvarchar(4000)
set @sqlstatement = 'Insert into #users (userID) SELECT userId FROM users'
exec(@sqlstatement)

declare users_cursor cursor for Select UserId from #Users
OPEN users_cursor
FETCH NEXT FROM users_cursor
INTO @UserId

WHILE @@FETCH_STATUS = 0
BEGIN

EXEC asp_DoSomethingStoredProc @UserId

FETCH NEXT FROM users_cursor
INTO @UserId

END
CLOSE users_cursor
DEALLOCATE users_cursor

drop table #users

다른 팁

이 코드는 @statement에서 '+'를 사용할 수 없기 때문에 커서가있는 동적 열에 대한 아주 좋은 예입니다.

ALTER PROCEDURE dbo.spTEST
AS
    SET NOCOUNT ON
    DECLARE @query NVARCHAR(4000) = N'' --DATA FILTER
    DECLARE @inputList NVARCHAR(4000) = ''
    DECLARE @field sysname = '' --COLUMN NAME
    DECLARE @my_cur CURSOR
    EXECUTE SP_EXECUTESQL
        N'SET @my_cur = CURSOR FAST_FORWARD FOR
            SELECT
                CASE @field
                    WHEN ''fn'' then fn
                    WHEN ''n_family_name'' then n_family_name
                END
            FROM
                dbo.vCard
            WHERE
                CASE @field
                    WHEN ''fn'' then fn
                    WHEN ''n_family_name'' then n_family_name
                END
                LIKE ''%''+@query+''%'';
            OPEN @my_cur;',
        N'@field sysname, @query NVARCHAR(4000), @my_cur CURSOR OUTPUT',
        @field = @field,
        @query = @query,
        @my_cur = @my_cur OUTPUT
    FETCH NEXT FROM @my_cur INTO @inputList
    WHILE @@FETCH_STATUS = 0
    BEGIN
        PRINT @inputList
        FETCH NEXT FROM @my_cur INTO @inputList
    END
    RETURN

ODBC 연결을 통한 비 관계형 데이터베이스 (IDMS 누구?)으로 작업하는 것은 커서와 동적 SQL이 유일한 경로 인 것처럼 보이는 시간 중 하나로 자격이됩니다.

select * from a where a=1 and b in (1,2)

IN 절을 사용하지 않고 키 세트를 사용하기 위해 다시 작성하는 동안 응답하는 데 45 분이 걸립니다.

select * from a where (a=1 and b=1)
union all
select * from a where (a=1 and b=2)

B 열의 진술에 1145 행이 포함 된 경우 커서를 사용하여 Indidivudal 문을 만들고 동적 SQL이 IN 절을 사용하는 것보다 훨씬 빠르기 때문에 실행합니다. 바보 야?

그렇습니다. 관계형 데이터베이스에는 커서를 사용해야 할 시간이 없습니다. 커서 루프가 몇 가지 더 빠른 인스턴스를 발견했다고 믿을 수 없습니다.

먼저 가능한 경우 커서를 사용하지 마십시오. 다음은 다음과 같이 할 수없는 것처럼 보일 때 근절하기위한 몇 가지 리소스입니다.

커서를 잃는 15 가지 방법이 있어야합니다 ... 1 부, 소개

커서가없는 행으로 처리

그러나 즉, 당신은 결국 하나에 갇혀있을 수 있습니다. 나는 당신의 질문에서 충분히 알지 못합니다. 이 경우 다른 문제가 있다면 커서의 선택 설명은 실제 실행 명령문이 아닌 명령문을 선택하십시오. 당신은 붙어 있습니다.

그러나 임시 테이블 사용에 대한 CMSJR (내가 글을 쓰는 동안 들어온)의 답변을 참조하십시오. 나는 피할 것이다 글로벌 "평범한"것 이상의 커서 ....

최근 Oracle에서 SQL Server (고용주 선호도)로 전환 한 후 SQL Server의 커서 지원이 지연되고 있음을 알 수 있습니다. 커서는 항상 악한 것은 아니며 때로는 필요하며 때로는 훨씬 빠르며 때로는 훨씬 더 깨끗하지 않습니다. "커서는 악한"의견은 SQL Server 커뮤니티에서 훨씬 더 두드러집니다.

그래서이 대답은 Oracle로 전환하거나 MS에게 단서를주는 것이라고 생각합니다.

내가 당신과 공유하고 싶은 또 다른 예가 있습니다.
:디http://www.sommarskog.se/dynamic_sql.html#cursor0

SQL Server의 또 다른 옵션은 저장된 Proc에서 모든 동적 쿼리를 테이블 변수로 수행 한 다음 커서를 사용하여 쿼리 및 처리하는 것입니다. 두려운 커서 토론에 관해서는 :), 나는 어떤 상황에서는 제대로 설정하면 커서가 실제로 더 빠를 수 있음을 보여주는 연구를 보았습니다. 필요한 쿼리가 너무 복잡하거나 인간적으로 (나를 위해)가 불가능할 때 직접 사용합니다.

이 코드는 귀하에게 유용 할 수 있습니다.

SQL Server에서 커서 사용의 예

DECLARE sampleCursor CURSOR FOR 
      SELECT K.Id FROM TableA K WHERE ....;
OPEN sampleCursor
FETCH NEXT FROM sampleCursor INTO @Id
WHILE @@FETCH_STATUS <> -1
BEGIN

UPDATE TableB
   SET 
      ...
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top