Using a cursor with dynamic SQL in a stored procedure

前端 未结 8 2199
佛祖请我去吃肉
佛祖请我去吃肉 2020-11-29 21:37

I have a dynamic SQL statement I\'ve created in a stored procedure. I need to iterate over the results using a cursor. I\'m having a hard time figuring out the right syntax.

相关标签:
8条回答
  • 2020-11-29 21:56

    A cursor will only accept a select statement, so if the SQL really needs to be dynamic make the declare cursor part of the statement you are executing. For the below to work your server will have to be using global cursors.

    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
    

    If you need to avoid using the global cursors, you could also insert the results of your dynamic SQL into a temporary table, and then use that table to populate your cursor.

    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
    
    0 讨论(0)
  • 2020-11-29 21:58

    There is another example which I would like to share with you
    :D http://www.sommarskog.se/dynamic_sql.html#cursor0

    0 讨论(0)
  • 2020-11-29 22:00

    Another option in SQL Server is to do all of your dynamic querying into table variable in a stored proc, then use a cursor to query and process that. As to the dreaded cursor debate :), I have seen studies that show that in some situations, a cursor can actually be faster if properly set up. I use them myself when the required query is too complex, or just not humanly (for me ;) ) possible.

    0 讨论(0)
  • 2020-11-29 22:07

    After recently switching from Oracle to SQL Server (employer preference), I notice cursor support in SQL Server is lagging. Cursors are not always evil, sometimes required, sometimes much faster, and sometimes cleaner than trying to tune a complex query by re-arranging or adding optimization hints. The "cursors are evil" opinion is much more prominent in the SQL Server community.

    So I guess this answer is to switch to Oracle or give MS a clue.

    • Oracle EXECUTE IMMEDIATE into a cursor
    • Loop through an implicit cursor (a for loop implicitly defines/opens/closes the cursor!)
    0 讨论(0)
  • 2020-11-29 22:08

    This code is a very good example for a dynamic column with a cursor, since you cannot use '+' in @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
    
    0 讨论(0)
  • 2020-11-29 22:09

    this code can be useful for you.

    example of cursor use in 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 
          ...
    
    0 讨论(0)
提交回复
热议问题