INF: Explanation of Error Message 16929, Cursor Is Read-Only

Last reviewed: April 9, 1997
Article ID: Q158773
The information in this article applies to:
  • Microsoft SQL Server, versions 6.0 and 6.5

SUMMARY

This article discusses the conditions that cause the following SQL Server error:

   Msg 16929, Level 16, State 1
   Cursor is read only

MORE INFORMATION

Message 16929 simply means that an update operation was attempted on a read- only cursor. Cursor update operations include doing an UPDATE, INSERT, or DELETE command specifying a WHERE CURRENT OF clause that references the read-only cursor.

By definition, an insensitive (or static) cursor is a read-only cursor, as is a cursor declared with the FOR READ ONLY clause. For example, a cursor declared as:

   DECLARE xyz CURSOR FOR select * from authors

   -or-

   DECLARE abc SCROLL CURSOR FOR select * from authors

is updatable unless the select clause violates the restrictions on what SQL Server allows in an updatable cursor. The Transact-SQL Reference Manual section on cursors contains a description of the DECLARE statement. In the paragraphs discussing the select statement that can be specified as part of a DECLARE CURSOR command, the manual lists the limitations that prevent a cursor from being updatable. If a cursor is declared in SQL Server 6.0 with a select statement that does any of the following, the cursor will actually be created as a static, read-only cursor:
  • Does not reference any tables with at least one unique index or primary key constraint.
  • Contains DISTINCT, UNION, GROUP BY, or HAVING clauses.
  • Contains a constant expression in the select list.

You will receive message 16929 if you try to do an update operation (for example, doing an update, insert, or delete WHERE CURRENT OF the cursor) using such a cursor. In SQL Server 6.5, the requirement for a unique index or primary key constraint is dropped for the DECLARE xyz CURSOR statement.

For example, if you issue the following commands in SQL Server 6.0:

   CREATE TABLE NoIDX (cola int, colb char(8))
   go
   DECLARE MyCursor SCROLL CURSOR FOR
   select * from NoIDX
   FOR UPDATE
   go

the cursor MyCursor will be created, but it will be a static, read-only cursor because the table NoIDX does not have a primary key or unique index. Any later attempt to do an update, delete, or insert WHERE CURRENT OF MyCursor would fail with message 16929. With SQL Server 6.5, the behavior was changed so that the DECLARE CURSOR command will fail with message 16929 because the user had specified FOR UPDATE in a cursor that cannot support updates.

The most common cause for error 16929 is a cursor that references tables that do not have primary key constraints or unique indexes. In this case, simply create a primary key constraint or unique index on the table. If the cause of error 16929 is that the select statement in the DECLARE CURSOR command violates the limitations for updatable cursors, then see if the select statement can be recoded.

If the table structure will not support a unique index, or if the select statement cannot be recoded, the cursor will not be updatable. This simply means that you cannot reference the cursor in a WHERE CURRENT OF clause on an UPDATE, INSERT or DELETE command. However, the cursor can still be used to determine the position for an UPDATE, INSERT, or DELETE. Instead of doing a FETCH to position on a row and then doing an UPDATE WHERE CURRENT OF, the you could do a FETCH to retrieve the key values identifying the row to be affected, and then specify the key values in the WHERE clause of the UPDATE command. For example, instead of doing the following on the NoIDX table (created in the example above):

   DECLARE MyCursor SCROLL CURSOR FOR select * from NoIDX
   OPEN MyCursor
   FETCH FIRST FROM MyCursor
   UPDATE NoIDX SET colb = 'string' WHERE CURRENT OF MyCursor
   go

You could do the following:

   DECLARE @CurCola INT
   DECLARE MyCursor SCROLL CURSOR FOR select cola from NoIDX
   OPEN MyCursor
   FETCH FIRST FROM MyCursor INTO @CurCola
   UPDATE NoIDX SET colb = 'string' WHERE cola = @CurCola
   go


Additional query words:
Keywords : kbusage SSrvGen
Version : 6.0 6.5
Platform : WINDOWS


THE INFORMATION PROVIDED IN THE MICROSOFT KNOWLEDGE BASE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. MICROSOFT DISCLAIMS ALL WARRANTIES, EITHER EXPRESS OR IMPLIED, INCLUDING THE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL MICROSOFT CORPORATION OR ITS SUPPLIERS BE LIABLE FOR ANY DAMAGES WHATSOEVER INCLUDING DIRECT, INDIRECT, INCIDENTAL, CONSEQUENTIAL, LOSS OF BUSINESS PROFITS OR SPECIAL DAMAGES, EVEN IF MICROSOFT CORPORATION OR ITS SUPPLIERS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. SOME STATES DO NOT ALLOW THE EXCLUSION OR LIMITATION OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES SO THE FOREGOING LIMITATION MAY NOT APPLY.

Last reviewed: April 9, 1997
© 1998 Microsoft Corporation. All rights reserved. Terms of Use.