2011-08-31 81 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
  • OPENFETCHWHILECLOSEDEALLOCATE是錯誤的。
  • 您的臨時表需要每次創建。

試試這個重構的腳本。修改爲您需要:

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是臨時表(如果它已存在)。 CREATE位於該聲明的ELSE部分。這意味着如果表格已經存在,那麼它將會被重新制作並且不會被重新創建。

+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 + '%')