Cursor loop

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Chris Zopers

    Cursor loop

    Hello,

    I've created a stored procedure that loops through a cursor, with the
    following example code:

    DECLARE curPeriod CURSOR LOCAL for SELECT * FROM tblPeriods
    DECLARE @intYear smallint
    DECLARE @intPeriod smallint
    DECLARE @strTekst varchar(50)

    OPEN curPeriod

    WHILE @@FETCH_STATUS= 0

    BEGIN

    FETCH NEXT FROM curPeriod INTO @intYear, @intPeriod

    SET @strTekst = CONVERT(varchar , @intPeriod)

    PRINT @strTekst

    END

    CLOSE curPeriod
    DEALLOCATE curPeriod

    The problem is that this loop only executes one time, when I call the
    stored procedure a second or third time, nothing happens. It seems that
    the Cursor stays at the last record or that @@Fetch_status isn't 0. But
    I Deallocate the cursor. I have to restart the SQL Server before the
    stored procedure can be used again.

    Does anyone know why the loop can execute only 1 time?

    Greetings,
    Chris

    *** Sent via Developersdex http://www.developersdex.com ***
  • Damien

    #2
    Re: Cursor loop

    Chris Zopers wrote:
    Hello,
    >
    I've created a stored procedure that loops through a cursor, with the
    following example code:
    >
    DECLARE curPeriod CURSOR LOCAL for SELECT * FROM tblPeriods
    DECLARE @intYear smallint
    DECLARE @intPeriod smallint
    DECLARE @strTekst varchar(50)
    >
    OPEN curPeriod
    >
    WHILE @@FETCH_STATUS= 0
    >
    BEGIN
    >
    FETCH NEXT FROM curPeriod INTO @intYear, @intPeriod
    >
    SET @strTekst = CONVERT(varchar , @intPeriod)
    >
    PRINT @strTekst
    >
    END
    >
    CLOSE curPeriod
    DEALLOCATE curPeriod
    >
    The problem is that this loop only executes one time, when I call the
    stored procedure a second or third time, nothing happens. It seems that
    the Cursor stays at the last record or that @@Fetch_status isn't 0. But
    I Deallocate the cursor. I have to restart the SQL Server before the
    stored procedure can be used again.
    >
    Does anyone know why the loop can execute only 1 time?
    >
    Greetings,
    Chris
    Hi Chris,

    When you say you have to restart SQL Server before it can be used
    again, do you mean the server or just Query Analyser?

    I suspect the issue you're having is when you next enter the stored
    procedure, the FETCH_STATUS is still as it was at the end of the last
    time through the loop - non-zero, and so the loop isn't executed.

    I've never seen a good pattern for doing cursors that doesn't look
    messy (Since most practicioners tend to try to avoid them in the first
    place, no-one spends much time tidying them up).

    Normal pattern for me is:

    declare cursor x for select ...
    declare <variables to hold the columns>

    open x

    fetch next from x into <list of variables>
    while @@FETCH_STATUS = 0
    begin
    --Do stuff

    fetch next from x into <list of variables>
    end

    close x
    deallocate x

    in short, I've never found a way to do it which doesn't have to have
    the same fetch statement in two places.

    Damien

    PS - Usual recommendation would be to have a list of columns, rather
    than select * from.... However, there is disagreement over this
    particular recommendation, I'd suggest you search the archives for some
    lively debate on the matter.

    Comment

    • Erland Sommarskog

      #3
      Re: Cursor loop

      Chris Zopers (test123test12@ 12move.nl) writes:
      I've created a stored procedure that loops through a cursor, with the
      following example code:
      >
      DECLARE curPeriod CURSOR LOCAL for SELECT * FROM tblPeriods
      DECLARE @intYear smallint
      DECLARE @intPeriod smallint
      DECLARE @strTekst varchar(50)
      >
      OPEN curPeriod
      >
      WHILE @@FETCH_STATUS= 0
      BEGIN
      FETCH NEXT FROM curPeriod INTO @intYear, @intPeriod
      SET @strTekst = CONVERT(varchar , @intPeriod)
      PRINT @strTekst
      END
      >
      CLOSE curPeriod
      DEALLOCATE curPeriod
      >
      The problem is that this loop only executes one time, when I call the
      stored procedure a second or third time, nothing happens.
      This is because you check @@fetch_status before you fetch. This is how
      you should write cursor loop:

      DECLARE cur INSENSITIVE CURSOR FOR
      SELECT col1, col2 FROM tbl

      OPEN cur

      WHILE 1 = 1
      BEGIN
      FETCH cur INTO @par1, @par2
      IF @@fetch_status <0
      BREAK

      --- Do stuff
      END

      DEALLOCATE cur

      Beyond the structure of the cursor loop, please notice:

      1) Never use SELECT * with cursor declarations. Add a column to the
      table, and your code breaks. That's bad.

      2) The cursor must be declared as INSENSITIVE or STATIC (the latter
      can be combined with LOCAL, the first cannot). With no specification
      you get a dynamic cursor, which is rarely what you want. But dynamic
      cursors can have bad impact on both performance and funcion.

      --
      Erland Sommarskog, SQL Server MVP, esquel@sommarsk og.se

      Books Online for SQL Server 2005 at

      Books Online for SQL Server 2000 at

      Comment

      Working...