I appear to have made an error in this cursor and I can't seem to figure out what I have done wrong.

I've confirmed that the select pulls back 2 rows. But when I pass it into the cursor to pick appear the string and I can extract the exact value I need. The two rows look something like the following...


The cursor appears to grab the 1st row and continually loop around never getting onto the next row or end the program.

    @clobstringP varchar(max),
    @clobstring  varchar(max);

declare SevenCursor cursor for 
    select [value] as ClobP
    from string_split(@clobstring, '>')
    where value like '%<|2|%';

open SevenCursor;
fetch next from SevenCursor into @clobstringP;

while @@FETCH_STATUS = 0
    insert into [database].dbo.tablestuff ( ValueP ) 
    select file387
    from ( 
             RowId387 = row_number() over( order by ( select 1 ) )
            ,file387  = [value]
        from string_split(@clobstringP, '|')
    ) a
    where a.RowId387 = 6;


close SevenCursor;
deallocate SevenCursor;

Can someone point me in the right direction?

2 Answers 2


As Peter has pointed out, your loop will never end since you don't do a fetch inside the loop. I prefer to have only one FETCH to maintain instead of two. So, my loop structure for a cursor is as follows:

WHILE 1 = 1
  FETCH NEXT FROM OrdersCursor INTO @sales_person_id, @orderdate;
    IF @@FETCH_STATUS <> 0

  --Whatever it is I'm doing inside the loop

A matter of taste which you prefer...


The cursor will loop infinitely unless and until @@fetchstatus = 0. In order to reach that state, you need to proceed through the dataset. In order to do that, you should add fetch next from SevenCursor into @clobstringP; to the inside of the begin ... end block so that the cursor has something to iterate over.

It is perhaps prudent to editorialize a bit at this stage and recommend that you try to ditch the cursor entirely. Cursors are pretty nifty but are misused more often than not; and from your provided psuedo-code, it seems that perhaps you may be trying to fix X when you could bypass to Y.

I might suggestion taking the whole result set and string_split-ing it into a sensible #temp_table. When you've performed any necessary updates/deletes on this cached result set and verified it's suitable, try for a single insert into dbo.tablestuff ... to succeed or fail based on batch evaluated rules. For example:

declare @pipe_delimited_rows table ( 
    my_row varchar(max)
insert @pipe_delimited_rows ( my_row ) 

drop table if exists #cache_results; 
create table #cache_results ( 
     id int identity not null primary key
    ,ClobP nvarchar(max)

insert #cache_results ( ClobP )
select ss.[value] as ClobP
from @pipe_delimited_rows pdr
cross apply string_split(pdr.my_row, '>') ss -- delimiting appropriately here, of course
where ss.[value] like '%<|2|%';

/* perform business logic to validate interim results here */

insert into [database].dbo.tablestuff ( ValueP ) 
select ClobP
from #cache_results;



Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.