Continue from top in SQL SERVER Cursor? - sql

In C# language we use continue statement in a loop to move to next iteration. But in using Cursor in TSQL how can I perform the same. Let say I have,
DECLARE db_cursor CURSOR FOR SELECT age, name, color FROM table;
DECLARE #myName VARCHAR(256);
DECLARE #myAge INT;
DECLARE #myFavoriteColor VARCHAR(40);
OPEN db_cursor;
FETCH NEXT FROM db_cursor INTO #myName, #myAge, #myFavoriteColor;
WHILE ##FETCH_STATUS = 0
BEGIN
--Do stuff
IF #myAge=1
BEGIN
-- Use continue here
END
--Do stuff
FETCH NEXT FROM db_cursor INTO #myName, #myAge, #myFavoriteColor;
END;
CLOSE db_cursor;
DEALLOCATE db_cursor;

CONTINUE does go back to the start of the WHILE loop, but it's not exactly like in C#, since the cursor looping idiom in T-SQL is broken into two separate statements, and the WHILE is the second of them - the cleanest, requiring the least repetition, may be our old friend GOTO:
DECLARE db_cursor CURSOR FOR SELECT age, name, color FROM table;
DECLARE #myName VARCHAR(256);
DECLARE #myAge INT;
DECLARE #myFavoriteColor VARCHAR(40);
OPEN db_cursor;
FETCH NEXT FROM db_cursor INTO #myName, #myAge, #myFavoriteColor;
WHILE ##FETCH_STATUS = 0
BEGIN
--Do stuff
IF #myAge=1
BEGIN
Goto Cont
END
--Do stuff
Cont:
FETCH NEXT FROM db_cursor INTO #myName, #myAge, #myFavoriteColor;
END;
CLOSE db_cursor;
DEALLOCATE db_cursor;

you can use CONTINUE in this manner
DECLARE db_cursor CURSOR FOR SELECT age, name, color FROM table;
DECLARE #myName VARCHAR(256);
DECLARE #myAge INT;
DECLARE #myFavoriteColor VARCHAR(40);
OPEN db_cursor;
FETCH NEXT FROM db_cursor INTO #myName, #myAge, #myFavoriteColor;
WHILE ##FETCH_STATUS = 0
BEGIN
--Do stuff
IF #myAge=1
BEGIN
FETCH NEXT FROM db_cursor INTO #myName, #myAge, #myFavoriteColor;
CONTINUE;
END
--Do stuff
FETCH NEXT FROM db_cursor INTO #myName, #myAge, #myFavoriteColor;
END;
CLOSE db_cursor;
DEALLOCATE db_cursor;

Try this one -
DECLARE
#myName VARCHAR(256)
, #myAge INT
, #myFavoriteColor VARCHAR(40)
DECLARE cursor_name CURSOR FAST_FORWARD READ_ONLY FOR
SELECT age, name, color
FROM [table]
OPEN db_cursor
FETCH NEXT FROM db_cursor INTO
#myName
, #myAge
, #myFavoriteColor
WHILE ##FETCH_STATUS = 0 BEGIN
IF #myAge = 1 BEGIN
FETCH NEXT FROM db_cursor INTO
#myName
, #myAge
, #myFavoriteColor
END
FETCH NEXT FROM db_cursor INTO
#myName
, #myAge
, #myFavoriteColor
END
CLOSE db_cursor
DEALLOCATE db_cursor

Related

Delete multiple records from table through cursor in sql server

there are number of test IP's which I would like to remove through system defined sp
exec sp_delete_firewall_rule from sys.firewall_rules table in sql server
I am using below cursor but its not working
declare #name nvarchar(max)
declare cur CURSOR LOCAL for
select #name from sys.firewall_rules where [name] like '%TestIP%'
open cur
fetch next from cur into #name
while ##FETCH_STATUS = 0 BEGIN
exec sp_delete_firewall_rule #name
fetch next from cur into #name
END
close cur
deallocate cur
It worked for me, you just need to change a couple of things in your code.
In the select list include the table ColumnName [name] instead of variable. You did not pass any value to the variable so this gives a NULL result.
Include SP parameter while executing exec sp_delete_firewall_rule #name = #name1;
I have these IP’s in my firewall rules:
With the below code I am deleting the IP’s which has a name like TestIP1.
DECLARE #name1 nvarchar(128);
DECLARE MyCursor CURSOR FOR
SELECT [name] from sys.firewall_rules where [name] like '%TestIP1%';
OPEN MyCursor;
FETCH FROM MyCursor into #name1
WHILE ##FETCH_STATUS = 0 BEGIN
EXEC sp_delete_firewall_rule #name = #name1 ;
FETCH next from MyCursor into #name1
END
CLOSE MyCursor;
DEALLOCATE MyCursor;
GO
Now the result shows only 1 IP which is not included in the above delete list.

Transaction within a cursor

Is the following the correct way to use transactions within a cursor:
SET CURSOR_CLOSE_ON_COMMIT ON;
DECLARE cur CURSOR LOCAL FOR
SELECT * FROM #ordersToProcess;
OPEN cur;
DECLARE #OrderId int;
FETCH NEXT FROM cur INTO #OrderId;
WHILE ##FETCH_STATUS = 0 BEGIN
BEGIN TRY
BEGIN TRAN;
EXEC process_order #OrderId;
COMMIT TRAN;
DEALLOCATE cur;
SET CURSOR_CLOSE_ON_COMMIT OFF;
END TRY
BEGIN CATCH
ROLLBACK TRAN;
DEALLOCATE cur;
SET CURSOR_CLOSE_ON_COMMIT OFF;
THROW;
END CATCH;
FETCH NEXT FROM cur INTO #OrderId;
END;
No. You have this code:
WHILE ##FETCH_STATUS = 0 BEGIN
BEGIN TRY
BEGIN TRAN;
EXEC process_order #OrderId;
COMMIT TRAN;
DEALLOCATE cur;
SET CURSOR_CLOSE_ON_COMMIT OFF;
END TRY
. . .
This runs one time through the loop, deallocates the cursor and then . . . well, you have a problem on the second time through the loop.
I think you intend to dealloc after the while loop.
Deallocate and Close after the cursor has finished:
DECLARE cur CURSOR LOCAL FOR
SELECT * FROM #ordersToProcess;
OPEN cur;
DECLARE #OrderId int;
FETCH NEXT FROM cur INTO #OrderId;
WHILE ##FETCH_STATUS = 0 BEGIN
BEGIN TRY
BEGIN TRAN;
EXEC process_order #OrderId;
COMMIT TRAN;
END TRY
BEGIN CATCH
ROLLBACK TRAN;
THROW;
END CATCH;
FETCH NEXT FROM cur INTO #OrderId;
END;
BEGIN TRY
CLOSE Cursor1
DEALLOCATE Cursor1
END TRY
BEGIN CATCH
--Do nothing
END CATCH

Cursor not working in stored procedure

I am using cursor in ms sql server
DECLARE #LineOfAuthoritySubString varchar(100);
declare #tbProductId int;
declare #tbLineOfAuthorityId int;
DECLARE #MyCursor CURSOR
SET #MyCursor = CURSOR FAST_FORWARD
FOR
Select TempLineOfAuthority FROM #tbTempLineOfAuthority
OPEN #MyCursor
FETCH NEXT FROM #MyCursor
INTO #LineOfAuthoritySubString
WHILE ##FETCH_STATUS = 0
BEGIN
Set #tbLineOfAuthorityId = (Select LineOfAuthority
from tbLineOfAuthority where LineOfAuthorityX = #LineOfAuthorityNameSubString);
INSERT INTO tbProductLineOfAuthority(ProductId, LineOfAuthortyId)
VALUES(#tbProductId, #tbLineOfAuthorityId);
FETCH NEXT FROM #MyCursor
INTO #LineOfAuthoritySubString
END
CLOSE #MyCursor
DEALLOCATE #MyCursor
It's not working. It is assigning null value to the variable #tbLineOfAuthorityId.
You are inserting cursor value in #LineOfAuthoritySubString and in where condition #LineOfAuthorityNameSubString variable is used
Both variable name is mismatched.
FETCH NEXT FROM #MyCursor INTO #LineOfAuthoritySubString
IN above you are fetching value in variable #LineOfAuthoritySubString .
Set #tbLineOfAuthorityId = (Select LineOfAuthority from tbLineOfAuthority where LineOfAuthorityX = #LineOfAuthorityNameSubString);
But when you are selecting from table tbLineOfAuthority, observe the variable you are using in where query.
It should be #LineOfAuthoritySubString and not #LineOfAuthorityNameSubString
pleae try below edited query if it works.
DECLARE #LineOfAuthoritySubString varchar(100);
declare #tbProductId int;
declare #tbLineOfAuthorityId int;
DECLARE #MyCursor CURSOR
SET #MyCursor = CURSOR FAST_FORWARD
FOR
Select TempLineOfAuthority FROM #tbTempLineOfAuthority
OPEN #MyCursor
FETCH NEXT FROM #MyCursor
INTO #LineOfAuthoritySubString
WHILE ##FETCH_STATUS = 0
BEGIN
Set #tbLineOfAuthorityId = (Select LineOfAuthority
from tbLineOfAuthority where LineOfAuthorityX = #LineOfAuthoritySubString);
INSERT INTO tbProductLineOfAuthority(ProductId, LineOfAuthortyId)
VALUES(#tbProductId, #tbLineOfAuthorityId);
FETCH NEXT FROM #MyCursor
INTO #LineOfAuthoritySubString
END
CLOSE #MyCursor
DEALLOCATE #MyCursor

Sql cursor in infinite loop. What is wrong in this code?

Hi I am trying to loop for each employee id in table.
BEGIN
declare #empId nvarchar(50)
declare cur Cursor LOCAL for
select EmpId from EmployeeMaster
open cur
fetch next from cur into #empId
while ##FETCH_STATUS =0
begin
select #empId
end
close cur
END
This is my query in stored procedure. What is wrong with this? it is giving me first employee id within infinite loop.
If i check while ##FETCH_STATUS =1 then no output given. just saying
Command(s) completed successfully.
You need to add fetch command after select
BEGIN
declare #empId nvarchar(50)
declare cur Cursor LOCAL for
select EmpId from EmployeeMaster
open cur
fetch next from cur into #empId
while ##FETCH_STATUS =0
begin
select #empId
fetch next from cur into #empId
end
close cur
END

Get Multiple Values in SQL Server Cursor

I have a cursor containing several columns from the row it brings back that I would like to process at once. I notice most of the examples I've seeing on how to use cursors show them assigning a particular column from the cursor to a scalar value one at a time, then moving to the next row,
e.g.
OPEN db_cursor
FETCH NEXT FROM db_cursor INTO #name
WHILE ##FETCH_STATUS = 0
BEGIN
--Do Stuff with #name scalar value, then get next row from cursor
FETCH NEXT FROM db_cursor INTO #name
END
What I want to know is if it's possible to do something like the following:
OPEN db_cursor
FETCH NEXT FROM db_cursor;
WHILE ##FETCH_STATUS = 0
BEGIN
SET #myName = db_cursor.name;
SET #myAge = db_cursor.age;
SET #myFavoriteColor = db_cursor.favoriteColor;
--Do stuff with scalar values
FETCH NEXT FROM db_cursor;
END
Help is always appreciated.
This should work:
DECLARE db_cursor CURSOR FOR SELECT name, age, color FROM table;
DECLARE #myName VARCHAR(256);
DECLARE #myAge INT;
DECLARE #myFavoriteColor VARCHAR(40);
OPEN db_cursor;
FETCH NEXT FROM db_cursor INTO #myName, #myAge, #myFavoriteColor;
WHILE ##FETCH_STATUS = 0
BEGIN
--Do stuff with scalar values
FETCH NEXT FROM db_cursor INTO #myName, #myAge, #myFavoriteColor;
END;
CLOSE db_cursor;
DEALLOCATE db_cursor;
Do not use ##fetch_status - this will return status from the last cursor in the current connection. Use the example below:
declare #sqCur cursor;
declare #data varchar(1000);
declare #i int = 0, #lastNum int, #rowNum int;
set #sqCur = cursor local static read_only for
select
row_number() over (order by(select null)) as RowNum
,Data -- you fields
from YourIntTable
open #cur
begin try
fetch last from #cur into #lastNum, #data
fetch absolute 1 from #cur into #rowNum, #data --start from the beginning and get first value
while #i < #lastNum
begin
set #i += 1
--Do your job here
print #data
fetch next from #cur into #rowNum, #data
end
end try
begin catch
close #cur --|
deallocate #cur --|-remove this 3 lines if you do not throw
;throw --|
end catch
close #cur
deallocate #cur