InicioArticulos y noticiasBases de datosProgramaciónForosInternetServiciosContratacionEmail
Tutorial de Transact SQL
Introducción a Transact SQL
Programación con Transact SQL
Fundamentos de Transact SQL
Tipos de datos en Transact SQL
Variables en Transact SQL
Equivalencia de datos de SQL Server y .NET
Operadores en Transact SQL
Estructuras de control en Transact SQL
Control de errores en Transact SQL
Consultar datos en Transact SQL
Consultas agregadas
Select FOR XML
Operaciones con conjuntos.
Insertar datos en Transact SQL
Actualizar datos en Transact SQL
Borrar datos en Transact SQL
Transacciones en Transact SQL
Procedimientos almacenados en Transact SQL
Funciones en Transact SQL
Funciones integradas de Transact SQL (I)
Triggers en Transact SQL
Cursores en Transact SQL
SQL dinámico en Transact SQL
También puedes ver ...
Simular TRUNC en SQL Server
Cómo insertar un fichero .xml en un campo de tipo XML de SQL server 2005 o 2008
SET IDENTITY_INSERT ON y LinqToSQL
SQL Server 2008
LinQ To SQL - Un ejemplo sencillo
Formatear números en SQL Server
Leer un campo XML de SQL Server 2005 con C#
Funciones integradas de Transact SQL (I)
SQL dinámico en Transact SQL
Triggers en Transact SQL


Cursores en Transact SQL

    Un cursor es una variable que nos permite recorrer con un conjunto de resultados obtenido a través de una sentencia SELECT fila a fila.

    Cuando trabajemos con cursores debemos seguir los siguientes pasos.

  • Declarar el cursor, utilizando DECLARE
  • Abrir el cursor, utilizando OPEN
  • Leer los datos del cursor, utilizando FETCH ... INTO
  • Cerrar el cursor, utilizando CLOSE
  • Liberar el cursor, utilizando DEALLOCATE

    La sintaxis general para trabajar con un cursor es la siguiente.


-- Declaración del cursor

DECLARE <nombre_cursor> CURSOR

FOR

<sentencia_sql>

 

-- apertura del cursor

OPEN <nombre_cursor>

 

-- Lectura de la primera fila del cursor

FETCH <nombre_cursor> INTO <lista_variables>

 

WHILE (@@FETCH_STATUS = 0)

BEGIN

-- Lectura de la siguiente fila de un cursor

FETCH <nombre_cursor> INTO <lista_variables>

...

END -- Fin del bucle WHILE

 

-- Cierra el cursor

CLOSE <nombre_cursor>

-- Libera los recursos del cursor

DEALLOCATE <nombre_cursor>

    El siguente ejemplo muestra el uso de un cursor. 


-- Declaracion de variables para el cursor

DECLARE @Id int,

@Nombre varchar(255),

@Apellido1 varchar(255),

@Apellido2 varchar(255),

@NifCif varchar(20),

@FxNacimiento datetime


-- Declaración del cursor

DECLARE cClientes CURSOR FOR

SELECT Id, Nombre, Apellido1,
Apellido2
, NifCif, FxNacimiento

FROM CLIENTES

-- Apertura del cursor

OPEN cClientes

-- Lectura de la primera fila del cursor

FETCH cClientes INTO @id, @Nombre, @Apellido1,
@Apellido2
, @NifCif, @FxNacimiento

 

WHILE (@@FETCH_STATUS = 0 )

BEGIN

PRINT @Nombre + ' ' + @Apellido1 + ' ' + @Apellido2

-- Lectura de la siguiente fila del cursor

FETCH cClientes INTO @id, @Nombre, @Apellido1,
@Apellido2
, @NifCif, @FxNacimiento

END

 

-- Cierre del cursor

CLOSE cClientes

-- Liberar los recursos

DEALLOCATE cClientes

    Cuando trabajamos con cursores, la funcion @@FETCH_STATUS nos indica el estado de la última instrucción FETCH emitida, los valores posibles son:

Valor devuelto Descripción

0

La instrucción FETCH se ejecutó correctamente.

-1

La instrucción FETCH no se ejecutó correctamente o la fila estaba más allá del conjunto de resultados.

-2

Falta la fila recuperada.

    En la apertura del cursor, podemos especificar los siguientes parámetros:


DECLARE
<nombre_cursor> CURSOR

[ LOCAL | GLOBAL ]

[ FORWARD_ONLY | SCROLL ]

[ STATIC | KEYSET | DYNAMIC | FAST_FORWARD ]

[ READ_ONLY | SCROLL_LOCKS | OPTIMISTIC ]

[ TYPE_WARNING ]

FOR <sentencia_sql>

    El primer conjunto de parámetros que podemos especificar es [ LOCAL | GLOBAL ]. A continuación mostramos el significado de cada una de estas opciones.

  • LOCAL
    Especifica que el ámbito del cursor es local para el proceso por lotes, procedimiento almacenado o desencadenador en que se creó el cursor.


DECLARE
cClientes CURSOR LOCAL FOR

SELECT Id, Nombre, Apellido1,

Apellido2, NifCif, FxNacimiento

FROM CLIENTES

  • GLOBAL
    Especifica que el ámbito del cursor es global para la conexión. Puede hacerse referencia al nombre del cursor en cualquier procedimiento almacenado o proceso por lotes que se ejecute en la conexión.


DECLARE
cClientes CURSOR GLOBAL FOR

SELECT Id, Nombre, Apellido1,

Apellido2, NifCif, FxNacimiento

FROM CLIENTES

    Si no se especifica GLOBAL ni LOCAL, el valor predeterminado se controla mediante la configuración de la opción de base de datos default to local cursor.  

    El siguiente conjunto de parámetros que podemos especificar es [  FORWARD_ONLY | SCROLL  ]. A continuación mostramos el significado de cada una de estas opciones.

  • FORWARD_ONLY
    Especifica que el cursor sólo se puede desplazar de la primera a la última fila. FETCH NEXT es la única opción de recuperación admitida. 

 

DECLARE cClientes CURSOR FORWARD_ONLY FOR

SELECT Id, Nombre, Apellido1,

Apellido2, NifCif, FxNacimiento

FROM CLIENTES

  • SCROLL
    Especifica que están disponibles todas las opciones de recuperación (FIRST, LAST, PRIOR, NEXT, RELATIVE, ABSOLUTE). Si no se especifica SCROLL en una instrucción DECLARE CURSOR la única opción de recuperación que se admite es NEXT. No es posible especificar SCROLL si se incluye también FAST_FORWARD.
    Si se incluye la opción SCROLL, la forma en la realizamos la lectura del cursor varia, debiendo utilizar la siguiente sintaxis: FETCH [ NEXT | PRIOR | FIRST | LAST | RELATIVE | ABSOLUTE ] FROM < INTO

 

-- Declaracion de variables para el cursor

DECLARE @Id int,

@Nombre varchar(255),

@Apellido1 varchar(255),

@Apellido2 varchar(255),

@NifCif varchar(20),

@FxNacimiento datetime

 

-- Declaración del cursor

DECLARE cClientes CURSOR SCROLL FOR

SELECT Id, Nombre, Apellido1,

Apellido2, NifCif, FxNacimiento

FROM CLIENTES

-- Apertura del cursor

OPEN cClientes

-- Lectura de la primera fila del cursor

FETCH NEXT FROM cClientes

INTO @id, @Nombre, @Apellido1, @Apellido2, @NifCif, @FxNacimiento

 

WHILE (@@FETCH_STATUS = 0 )

BEGIN

PRINT @Nombre + ' ' + @Apellido1 + ' ' + @Apellido2

-- Lectura de la siguiente fila del cursor

FETCH NEXT FROM cClientes

INTO @id,@Nombre,@Apellido1,@Apellido2,@NifCif,@FxNacimiento

END

-- Lectura de la fila anterior

FETCH PRIOR FROM cClientes
INTO @id, @Nombre, @Apellido1, @Apellido2, @NifCif, @FxNacimiento

PRINT @Nombre + ' ' + @Apellido1 + ' ' + @Apellido2

-- Cierre del cursor

CLOSE cClientes

-- Liberar los recursos

DEALLOCATE cClientes

    El siguiente conjunto de parámetros que podemos especificar es [  STATIC | KEYSET | DYNAMIC | FAST_FORWARD ]. A continuación mostramos el significado de cada una de estas opciones.

  • STATIC
    Define un cursor que hace una copia temporal de los datos que va a utilizar. Todas las solicitudes que se realizan al cursor se responden desde esta tabla temporal de tempdb; por tanto, las modificaciones realizadas en las tablas base no se reflejan en los datos devueltos por las operaciones de recuperación realizadas en el cursor y además este cursor no admite modificaciones.

 

DECLARE cClientes CURSOR STATIC FOR

SELECT Id, Nombre, Apellido1,

Apellido2, NifCif, FxNacimiento

FROM CLIENTES

  • KEYSET
    Especifica que la pertenencia y el orden de las filas del cursor se fijan cuando se abre el cursor. El conjunto de claves que identifica las filas de forma única está integrado en la tabla denominada keyset de tempdb.

 

DECLARE cClientes CURSOR KEYSET FOR

SELECT Id, Nombre, Apellido1,

Apellido2, NifCif, FxNacimiento

FROM CLIENTES

  • DYNAMIC
    Define un cursor que, al desplazarse por él, refleja en su conjunto de resultados todos los cambios realizados en los datos de las filas. Los valores de los datos, el orden y la pertenencia de las filas pueden cambiar en cada operación de recuperación. La opción de recuperación ABSOLUTE no se puede utilizar en los cursores dinámicos.

 

DECLARE cClientes CURSOR DYNAMIC FOR

SELECT Id, Nombre, Apellido1,

Apellido2, NifCif, FxNacimiento

FROM CLIENTES

  • FAST_FORWARD
    Especifica un cursor FORWARD_ONLY, READ_ONLY con las optimizaciones de rendimiento habilitadas. No se puede especificar FAST_FORWARD si se especifica también SCROLL o FOR_UPDATE.

 

DECLARE cClientes CURSOR FAST_FORWARD FOR

SELECT Id, Nombre, Apellido1,

Apellido2, NifCif, FxNacimiento

FROM CLIENTES

    En SQL Server 2000, las opciones de cursor FAST_FORWARD y FORWARD_ONLY se excluyen mutuamente. Si se especifican ambas, se genera un error. En SQL Server 2005, las dos palabras clave se pueden utilizar en la misma instrucción DECLARE CURSOR.

    El siguiente conjunto de parámetros que podemos especificar es [  READ_ONLY | SCROLL_LOCKS | OPTIMISTIC  ]. A continuación mostramos el significado de cada una de estas opciones.

  • READ_ONLY
    Evita que se efectúen actualizaciones a través de este cursor. No es posible hacer referencia al cursor en una cláusula WHERE CURRENT OF de una instrucción UPDATE o DELETE. Esta opción reemplaza la capacidad de actualizar el cursor.

 

DECLARE cClientes CURSOR READ_ONLY FOR

SELECT Id, Nombre, Apellido1,

Apellido2, NifCif, FxNacimiento

FROM CLIENTES

  • SCROLL_LOCKS
    Especifica que se garantiza que las actualizaciones o eliminaciones posicionadas realizadas a través del cursor serán correctas. Microsoft SQL Server bloquea las filas cuando se leen en el cursor para garantizar que estarán disponibles para futuras modificaciones. No es posible especificar SCROLL_LOCKS si se especifica también FAST_FORWARD o STATIC.

 

DECLARE cClientes CURSOR SCROLL_LOCKS FOR

SELECT Id, Nombre, Apellido1,

Apellido2, NifCif, FxNacimiento

FROM CLIENTES

  • OPTIMISTIC
    Especifica que las actualizaciones o eliminaciones posicionadas realizadas a través del cursor no se realizarán correctamente si la fila se ha actualizado después de ser leída en el cursor. SQL Server no bloquea las filas al leerlas en el cursor. En su lugar, utiliza comparaciones de valores de columna timestamp o un valor de suma de comprobación si la tabla no tiene columnas timestamp, para determinar si la fila se ha modificado después de leerla en el cursor. Si la fila se ha modificado, el intento de actualización o eliminación posicionada genera un error. No es posible especificar OPTIMISTIC si se especifica también FAST_FORWARD.

 

DECLARE cClientes CURSOR OPTIMISTIC FOR

SELECT Id, Nombre, Apellido1,

Apellido2, NifCif, FxNacimiento

FROM CLIENTES

    Por último, queda la opción TYPE_WARNING

  • TYPE_WARNING
    Especifica que se envía un mensaje de advertencia al cliente si el cursor se convierte implícitamente del tipo solicitado a otro.

 

DECLARE cClientes CURSOR TYPE_WARNING FOR

SELECT Id, Nombre, Apellido1,

Apellido2, NifCif, FxNacimiento

FROM CLIENTES

    Podemos especificar multiples parámetros en la apertura de cursor, pero unicamente un parámetro de cada grupo. Por ejemplo:

 

DECLARE cClientes CURSOR LOCAL STATIC TYPE_WARNING FOR

SELECT Id, Nombre, Apellido1,

Apellido2, NifCif, FxNacimiento

FROM CLIENTES

    Para actualizar los datos de un cursor debemos especificar FOR UPDATE despues de la sentencia SELECT en la declaración del cursor, y WHERE CURRENT OF <nombre_cursor> en la sentencia UPDATE tal y como muestra el siguiente ejemplo.

-- Declaracion de variables para el cursor

DECLARE @Id int,

@Nombre varchar(255),

@Apellido1 varchar(255),

@Apellido2 varchar(255),

@NifCif varchar(20),

@FxNacimiento datetime

-- Declaración del cursor

DECLARE cClientes CURSOR FOR

SELECT Id, Nombre, Apellido1,

Apellido2, NifCif, FxNacimiento

FROM CLIENTES

FOR UPDATE

 

-- Apertura del cursor

OPEN cClientes

-- Lectura de la primera fila del cursor

FETCH cClientes
INTO @id, @Nombre, @Apellido1, @Apellido2, @NifCif, @FxNacimiento


WHILE
(@@FETCH_STATUS = 0 )

BEGIN

UPDATE Clientes

SET APELLIDO2 = isnull(@Apellido2,'') + ' - Modificado'

WHERE CURRENT OF cClientes

-- Lectura de la siguiente fila del cursor

FETCH cClientes
INTO @id, @Nombre, @Apellido1, @Apellido2,
@NifCif
, @FxNacimiento

END

-- Cierre del cursor

CLOSE cClientes

-- Liberar los recursos

DEALLOCATE cClientes

 


Inicio | Tutorial de Transact SQL Triggers en Transact SQLTutorial de Transact SQLSQL dinámico en Transact SQL Versión para imprimir Foros de consulta

 
pregunta por heysel
Respuesta recibida el [30/10/2007 03:30:38]
Como saber si estamos utilizando el tipo de cursor correcto a lo mejor me falla pero varios hacen lo mismo
o no les encuentro la diferencia espero tu respuesta la neta esta re chido tu tutorial

 
Saludos desde Bogota por Fredy Arias
Respuesta recibida el [01/11/2007 06:21:00]
Muchas gracias por facilitar de forma tan sencilla y clara este tutorial, tambien me lei el de PL/SQL y de veras me fueron  de mucha utilidad, gracias profe. 

 
Excelente por Jhonatan
Respuesta recibida el [16/11/2007 09:14:45]
Me ha resuelto un monton de dudas, Excelente!!!

 
buenos apuntes por Tomy de mexico
Respuesta recibida el [14/12/2007 10:48:06]
gracias por tus apuntes me han ayudado a entender cursores estoy empezando con este tipo de programacion..te estoy agradecido

 
Excelente por Lenin Paredes
Respuesta recibida el [16/02/2008 10:14:46]
Te felicito, muy bien explicado.
Ha sido de mucha utilidad, sobre todo la parte de actualizar datos a traves de un cursor, en fin, luego de revisarlo todo me he dado cuenta que has hecho un excelente trabajo, muchas gracias...!!!

 
GROSOOOO por Ruben
Respuesta recibida el [27/05/2008 11:17:22]
La verdad que sos mi libro de cabecera. Muchas Gracias por hacer esto para todos

 
CLARO por Miguel Mendez
Respuesta recibida el [28/05/2008 06:37:12]
En México no hay calidad en apuntes por web. MUCHAS GRACIAS.

 
Muy Bueno por Ronald
Respuesta recibida el [23/06/2008 11:22:36]
Gracias por la explicación, esta muy clara.

 
Buenísimo por Celina
Respuesta recibida el [27/06/2008 08:54:15]
Gracias! Excelente información...

 
Muy bueno!! por Guada
Respuesta recibida el [30/06/2008 11:31:44]
Te felicito por el tutorial, esta todo muy claro, y me fue de gran utilidad. Saludos!

 
GRACIAS!! por GLEN BENTON
Respuesta recibida el [01/07/2008 09:52:13]
MUCHAS GRACIAS MAESTRO!!!!

 
Buen manual por Arthur
Respuesta recibida el [30/08/2008 12:28:58]
Execelte manual,es dificil encontrar tan buena informacion junta.

 
En one por Geshu
Respuesta recibida el [22/09/2008 11:13:54]
Gracias por la información brindada, está como para aprender cursores en una sola lección... felicitaciones por el buen material

 
Buena Explicación por Walter
Respuesta recibida el [17/10/2008 11:48:45]
Ecxelente!!!, gracias me a sido de mucha ayuda 

 
Very Explicit por Susej
Respuesta recibida el [13/11/2008 12:38:58]
Me parece un muy buen tutorial ya que pedagogicamente hablando se expresa con un lenguaje bastante entendible.

 
Excelente Tutorial por Cristian
Respuesta recibida el [04/02/2009 10:08:51]
Muy buen tutorial para aprender a programar en Transact SQL Server, me sirvio muchisimo, gracias y ojala sigas brindando otros tutoriales tan buenos como este, saludos.

 
ejercicios por claudia
Respuesta recibida el [11/02/2009 01:36:28]
quisiera por favor ejercicios simples resueltos (para poder corregirme) de procedimientos almacenados, triggers y optimizacion de consultas. MUy bueno esto en cuanto a teoria!

 
Excelente tutorial por alesguz
Respuesta recibida el [14/05/2009 02:15:21]
Muy buena tu redacción, muy claro todo. Me ha servido bastante. Gracias.

 
update por frix
Respuesta recibida el [26/05/2009 05:22:35]
quisiera saber que es lo hace exactamente el WHERE CURRENT OF en un cursor que sirve para actualizar datos ya me que me marcaba error y quite esa sentencia y me hizo lo que queria que hiciera, que pasa si no lo pongo. muchas gracias, espero puedas ayudarme y corregirme.

 
respuesta por frix
Respuesta recibida el [08/06/2009 05:24:13]
creo que no he recibido respuesta de esto, si alguien mas me pudiera responder se los agradeciria

 
insensitive por PSD
Respuesta recibida el [13/08/2009 05:42:32]
y el parametro insensitive se sigue utilizando?

 
EXCELENTE por Ricardo
Respuesta recibida el [25/02/2010 05:38:58]
Mas de 3 años con el tema, y sigue ayudando a personas como yo en este momento, muchisimas gracias, eres un maestro


Añadir comentario ... Para preguntar utiliza los foros
Autor:

Título:


Para preguntar utiliza los foros.



Inicio | Tutorial de Transact SQL Triggers en Transact SQLTutorial de Transact SQLSQL dinámico en Transact SQL Versión para imprimir

Cursores en Transact SQL
Autor: Pedro Herrarte Sánchez
Visitas: 38327 Fecha de publicación: 06/11/2007
Pedro Herrarte, es consultor independiente, ofreciendo servicios de consultoría, análisis, desarrollo y formación.

Posee mas de diez años de experiencia trabajando para las principales empresas de España.

Es especialista en tecnologías .NET, entornos Web, bases de datos (SQL Server y ORACLE) e integración de sistemas.

Es experto en desarrollo (C#, ASP.NET, VB.Net, T-SQL, PL/SQL, , ASP, CGI , C, Pro*C, Java, Essbase, Vignette, PowerBuilder y Visual Basic ...) y bases de datos (SQL Server y ORACLE).

Es fundador, diseñador y programador de www.devjoker.com.




Visitas: 98 | Comentarios: 2 | Archivo: Articulos
02/02/2010 iPad vs Telesketch
Visitas: 798 | Comentarios: 2 | Archivo: Articulos
Categorias: Humor
Visitas: 753 | Comentarios: 3 | Archivo: Articulos
Visitas: 3158 | Comentarios: 2 | Archivo: Articulos
Categorias: C#
Visitas: 14520 | Comentarios: 7 | Archivo: Articulos
Categorias: C#|Seguridad
Visitas: 1484 | Comentarios: 3 | Archivo: Articulos
Visitas: 692 | Comentarios: 2 | Archivo: Articulos
Visitas: 369 | Comentarios: 0 | Archivo: Articulos
Visitas: 2022 | Comentarios: 2 | Archivo: Articulos
Categorias: C#

Útimos temas recibidos en los foros ...
certifiado de afiliacion por luz mary gerena ... [Actualidad] 2 26/02/2010
Ayuda por Nando ... [ORACLE] 1 12/03/2010
no me acuerdo donde estoy afiliada por girasol ... [Actualidad] 0 12/03/2010
quiero saber a que fondos estoy afiliado en pensiones y cesantias por rigo ... [Actualidad] 7 28/02/2010
pensiones por 29285524 ... [Access] 0 12/03/2010
certificado de porvenir por labar ... [Actualidad] 23 02/03/2010
Certificado de afiliacion Pensiones y Cesantias por VIVIANA ... [Actualidad] 2 10/03/2010
AYUDA COMANDOS BASICOS MSDOS!! por (L)MSDOS(L) ... [MS DOS] 24 12/03/2010
mananis por mananis ... [Actualidad] 0 12/03/2010
CERTIFICADO DE PENSIONES Y CESANTIAS PORVENIR por ABELLO ... [Actualidad] 0 12/03/2010
Solicitud certificado de afiliaciones a pensiones y cesantias proteccion por hz ... [Actualidad] 55 10/02/2010
certificado de pensiones y cesantias que me exigen para trabajar por viviana ... [Actualidad] 1 12/03/2010

Access CGI JSP ORACLE UNIX
Actualidad HTML/DHTML/XHTML LINUX PHP Visual Basic .NET
ASP ISAPI MS DOS Power Builder Visual Basic 6.0
ASP.NET Java mySQL SQL WIN 98/NT/2000/XP
C# JavaScript Opinion SQL Server

devjoker  Te recomendamos además ...
19/08/2006 Virtualización. Maquinas Virtuales.
13/10/2009 Insertar una marca de agua en documentos PDF
03/10/2006 Introduccion a C#    forma parte de...Tutorial C#
22/10/2005 El lenguaje SQL    forma parte de...Tutorial SQL
01/01/2006 Consultas agregadas    forma parte de...Tutorial SQL
03/10/2006 Programacion con C#    forma parte de...Tutorial C#
01/01/2006 Borrado de datos. DELETE    forma parte de...Tutorial SQL
09/05/2006 Como leer XML con C#
06/11/2007 Cursores en Transact SQL    forma parte de...Tutorial de Transact SQL
08/03/2007 Cambiar el nombre del servidor SQL Server

 

Encuesta
¿A que perfil te adaptas mejor?




[Ver] [Votar]