2011-08-31 3 views
1
나는 다음과 같은 오류를 얻고있다하지만 왜 알아낼 수 없습니다

..SQL 커서 문제

메시지 16915, 수준 16, 상태 1, 프로 시저 client_myClientsProc, 라인 46
이름 '으로 커서 cur_keywords '가 이미 존재합니다.
메시지 16905, 수준 16, 상태 1, 절차 client_myClientsProc, 줄 커서가 이미 열려 있습니다. 나는 다시 그것을 실행하려고하면

그리고는 그것은

메시지 208, 수준 16, 상태 0, 절차 client_myClientsProc 라인 49
잘못된 개체 이름 '## CLIENTS_KEYWORD을 말한다.

지금이 ================= ...

ALTER PROCEDURE [dbo].[client_myclientsproc] 
    @Keywords varchar(max), 
    @Delimiter varchar(10) = ' ' 
AS 
BEGIN 
    SET NOCOUNT ON; 

    DECLARE @MYQUERY NVARCHAR(MAX);  
    DECLARE @tempkeyword varchar(4000)  
    DECLARE @TempCount INT 

    IF OBJECT_ID('TempDB..##CLIENTS_KEYWORD') IS NOT NULL 
    BEGIN 
    DROP TABLE ##CLIENTS_KEYWORD 
    END 
    ELSE 
    BEGIN 
    CREATE TABLE ##CLIENTS_KEYWORD(client_id int) 
    END 

    IF OBJECT_ID('TempDB..##TEMP_CLIENTS_KEYWORD') IS NOT NULL 
    BEGIN 
    DROP TABLE ##TEMP_CLIENTS_KEYWORD 
    END 
    ELSE 
    BEGIN 
    CREATE TABLE ##TEMP_CLIENTS_KEYWORD(productid int) 
    END 

    SET @MYQUERY = 'SELECT clientID, Client_Name FROM MYCLIENTS WHERE ClientID IN ';      

IF(@Delimiter<>'none') 
BEGIN 
    DECLARE cur_keywords CURSOR FOR 
    select value from SC_Split(@Keywords,@Delimiter)  

    OPEN cur_keywords 

    FETCH NEXT FROM cur_keywords into @tempkeyword 
    INSERT ##CLIENTS_KEYWORD(client_id) exec getClientsByKeyword @tempkeyword 

    WHILE @@FETCH_STATUS = 0  

    FETCH NEXT FROM cur_keywords into @tempkeyword 

    INSERT ##TEMP_CLIENTS_KEYWORD(client_id) exec getClientsByKeyword @tempkeyword 
      select @TempCount=COUNT(client_id) from ##TEMP_CLIENTS_KEYWORD  
      IF(@TempCount<>0)  
       BEGIN  
        DELETE FROM ##CLIENTS_KEYWORD WHERE client_id NOT IN(SELECT client_id from ##TEMP_CLIENTS_KEYWORD)  
     INSERT ##CLIENTS_KEYWORD (client_id) (select client_id from ##TEMP_CLIENTS_KEYWORD)      
       END 
     CLOSE cur_keywords        
     DEALLOCATE cur_keywords         
END 
ELSE 
BEGIN 
    print(@Keywords) 
    INSERT ##CLIENTS_KEYWORD(client_id) exec getClientsByKeyword @Keywords  
END 

SET @MYQUERY = @MYQUERY + '(SELECT * FROM ##CLIENTS_KEYWORD)'       
SET @MYQUERY = @MYQUERY + ' ORDER BY NAME'      

print @MYQUERY 

EXEC SP_EXECUTESQL @MYQUERY           
END 
GO 

내가 그렇게 나를 참아주세요, 해결하기 위해 노력하고 예전의 코드입니다 ===

얻을 키워드 코드에 의해 클라이언트

CREATE PROCEDURE [dbo].[getClientsByKeyword] 
@Keyword varchar(max) 

AS 
BEGIN 
SET NOCOUNT ON; 


select      
    DISTINCT(clients.clientID) 
from      
    Clients_Table clients        
    left join clientNumber cn on cn.clientid=clients.clientid      
where      
    clients.activeind = 1      
    and (clients.Name like '%' + @Keyword + '%'      
    or clients.clientNum LIKE '%' + @Keyword + '%'   
    or cn.clientN like '%' + @Keyword + '%')  

END 



GO 
+1

어떤 SQL Server 버전을 사용하고 있습니까? –

+0

내 버전은 2008입니다 – user710502

+0

'getClientsByKeyword'는 무엇을합니까? 단순한 조인으로 바꾸거나 (더 복잡한 경우) 논리를 테이블 값의 함수에 넣으면 커서를 완전히 삭제할 수 있습니다. –

답변

4
  • OPEN, FETCH, WHILE, CLOSEDEALLOCATE는 잘못 귀하이다.
  • 매번 임시 테이블을 생성해야합니다.

이 리팩토링 된 스크립트를 사용해보십시오. 당신이 필요로 수정

DECLARE @tempkeyword varchar(4000)  
DECLARE @TempCount INT 

IF OBJECT_ID('TempDB..##CLIENTS_KEYWORD') IS NOT NULL 
    DROP TABLE ##CLIENTS_KEYWORD 

CREATE TABLE ##CLIENTS_KEYWORD(client_id int) 

IF OBJECT_ID('TempDB..##TEMP_CLIENTS_KEYWORD') IS NOT NULL 
    DROP TABLE ##TEMP_CLIENTS_KEYWORD 

CREATE TABLE ##TEMP_CLIENTS_KEYWORD(productid int) 

SET @MYQUERY = 'SELECT clientID, Client_Name FROM MYCLIENTS WHERE ClientID IN ';      

IF(@Delimiter<>'none') 
BEGIN  
    DECLARE cur_keywords CURSOR FOR 
     SELECT value FROM SC_Split(@Keywords,@Delimiter)  

     OPEN cur_keywords 
     FETCH NEXT FROM cur_keywords into @tempkeyword 
     WHILE @@FETCH_STATUS = 0  
     BEGIN 
     FETCH NEXT FROM cur_keywords into @tempkeyword 

     INSERT ##CLIENTS_KEYWORD(client_id) exec getClientsByKeyword @tempkeyword    
     INSERT ##TEMP_CLIENTS_KEYWORD(client_id) exec getClientsByKeyword @tempkeyword 
     SELECT @TempCount=COUNT(client_id) from ##TEMP_CLIENTS_KEYWORD  
     IF(@TempCount<>0)  
     BEGIN  
       DELETE FROM ##CLIENTS_KEYWORD 
        WHERE client_id NOT IN(SELECT client_id from ##TEMP_CLIENTS_KEYWORD); 

        INSERT ##CLIENTS_KEYWORD (client_id) 
        SELECT client_id from ##TEMP_CLIENTS_KEYWORD; 
     END 
     END 

    CLOSE cur_keywords        
    DEALLOCATE cur_keywords         
END 
ELSE 
BEGIN 
    print(@Keywords) 
    INSERT ##CLIENTS_KEYWORD(client_id) exec getClientsByKeyword @Keywords  
END 

SELECT @[email protected] + '(SELECT * FROM ##CLIENTS_KEYWORD) ORDER BY NAME'       
print @MYQUERY 
EXEC SP_EXECUTESQL @MYQUERY           
END 
2

저장 프로 시저 오류가 밖으로 이전 했습니까? CLOSEDEALLOCATE 문이 실행되지 않은 것 같습니다. 코드에 오류가 발생하여 코드 나 기타 방법에 TRY..CATCH이 없으므로 커서가 제대로 지워 졌는지 확인할 수 있습니다. 연결을 해제하거나 동일한 연결에서 CLOSEDEALLOCATE을 수동으로 실행 한 다음 다시 실행 해보십시오.

두 번째 오류는 비슷한 이유 때문일 수 있습니다. 즉, 정리가 잘못되었습니다. 저장 프로 시저를 입력하면 DROP 임시 테이블이 이미있는 경우 코드가 입력됩니다. 그래도 CREATEELSE 부분에 있습니다. 즉, 표가 이미 존재하는 경우 DROP 보너스가되며 다시 생성되지 않습니다.

+0

Gotcha에게 조언 해 주셔서 감사합니다. – user710502

1

테스트 테이블 난 당신의 코드가 무엇을하고 있는지 확인 정말 모르겠어요하지만 당신은 아마 아래를 기반으로 뭔가 전혀 커서의 사용을 피할 수 있다고 생각이 끝을 설정하지 않고.

;WITH C 
    AS (select clients.clientID, 
       clients.Name, 
       clients.clientNum, 
       cn.clientN 
     from Clients_Table clients 
       left join clientNumber cn 
        on cn.clientid = clients.clientid 
        AND clients.activeind = 1) 
select value, 
     clients.clientID 
from SC_Split(@Keywords, @Delimiter) 
     JOIN C 
     ON (C.Name like '%' + value + '%' 
       or C.clientNum LIKE '%' + value + '%' 
       or C.clientN like '%' + value + '%')