sql-server add tag
Hannah Vernon
When writing a cursor in T-SQL, I typically use the following template:

```
DECLARE @var varchar(10);
DECLARE cur CURSOR LOCAL FORWARD_ONLY READ_ONLY STATIC
FOR 
SELECT gender
FROM (VALUES ('what'), ('is'), ('gender'), ('anyway'))v(gender);

OPEN cur;
FETCH NEXT FROM cur INTO @var;

WHILE @@FETCH_STATUS = 0
BEGIN
    PRINT @var;
	FETCH NEXT FROM cur INTO @var;
END;
CLOSE cur;
DEALLOCATE cur;
```

For the most part this always work well, and isn't all *that* tragic, however [Microsoft Docs](https://docs.microsoft.com/en-us/sql/t-sql/functions/cursor-status-transact-sql?view=sql-server-ver15) shows that `CURSOR_STATUS` can be used to check the status of the cursor.  How is that different from `@@FETCH_STATUS` and how should `@@CURSOR_ROWS` be used to write effective cursor code that works all the time, ala Defensive Programming?

Also, is there anything else that should be done in cursor code to appease [Urutengangana](https://en.wikipedia.org/wiki/Urutengangana)?
Top Answer
Hannah Vernon
`CURSOR_STATUS` provides a nice way of ensuring the cursor is ready and contains rows.

The following code shows a way to check the status of the cursor prior to cursing through the potential resultset:

```
DECLARE @var varchar(10);
DECLARE @cursorStatus smallint;
DECLARE @cursorRows bigint;
DECLARE cur CURSOR LOCAL FORWARD_ONLY READ_ONLY STATIC
FOR 
SELECT gender
FROM (VALUES ('what'), ('is'), ('gender'), ('anyway'))v(gender);

OPEN cur;
SET @cursorStatus = CURSOR_STATUS('local', 'cur');
SET @cursorRows = @@CURSOR_ROWS;
PRINT 'Cursor contains ' + CONVERT(varchar(30), @cursorRows) + ' rows.';
IF @cursorStatus = 1
BEGIN
    FETCH NEXT FROM cur INTO @var;

    WHILE @@FETCH_STATUS = 0
    BEGIN
        PRINT @var;
	    FETCH NEXT FROM cur INTO @var;
    END;
END
ELSE
BEGIN
    DECLARE @msg varchar(1000) = 'Cursor not open, or has no rows.
CURSOR_STATUS returned: ';
    SET @msg = @msg + CONVERT(varchar(10), @cursorStatus);
    RAISERROR (@msg, 10, 1) WITH NOWAIT;
END
CLOSE cur;
DEALLOCATE cur;
```

You'll also notice that I've implemented `@@CURSOR_ROWS` to show the number of rows the cursor returned.


Enter question or answer id or url (and optionally further answer ids/urls from the same question) from

Separate each id/url with a space. No need to list your own answers; they will be imported automatically.