SQL游标问题

问题描述:

我收到以下错误,但无法弄清楚为什么..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是做什么的?用一个简单的连接来代替它会简单吗?或者(如果更复杂的话)把逻辑放到一个表值函数中,那么你可以完全放下光标。 –

  • 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 

做的存储过程的错误了以前?它看起来像CLOSEDEALLOCATE语句没有运行,这可能会发生,如果代码遇到错误,因为代码或其他方法中没有TRY..CATCH,以确保游标已被正确清除。尝试断开连接(或在同一连接中手动运行CLOSEDEALLOCATE)并再次运行。

第二个错误可能是由于类似的原因 - 糟糕的清理。当您输入存储过程时,代码DROP是临时表(如果它已存在)。 CREATE位于该声明的ELSE部分。这意味着如果表格已经存在,那么它将会被重新制作并且不会被重新创建。

+0

Gotcha感谢您的意见 – user710502

没有建立测试表为此我真的不知道你的代码是做什么,但我想你也许能避免使用光标在所有基于下面的东西。

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