Uso de cursores y bucles en Transact-SQL. Cursores en procedimientos almacenados MySQL Cursores en servidor SQL

El comando DECLARE CURSOR le permite recuperar registros de una tabla fila por fila para su manipulación. Esto permite el procesamiento fila por fila en lugar del procesamiento tradicional de conjuntos de datos que realiza SQL.

Como primera aproximación, se utilizan los siguientes pasos cuando se trabaja con el cursor.

El cursor se crea con el comando DECLARE. El cursor se abre con el comando ABRIR.

Las operaciones con el cursor se realizan mediante el comando FETCH. El cursor se cierra con el comando CERRAR.

El comando DECLARE CURSOR especifica una instrucción SELECT. Cada fila devuelta por la instrucción SELECT se puede recuperar y procesar individualmente. El siguiente ejemplo de Oracle declara un cursor en un bloque de declaración junto con varias otras variables. Después de esto, en el siguiente bloque BEGIN...END, se abre el cursor, se realiza una selección y se cierra el cursor.

CURSOR title_price_cursor ES SELECCIONAR título, precio DE títulos

DONDE el precio NO ES NULO; title_price_val title_price_cursor ROWTYPE; nuevo_precio NÚMERO (10.2);

ABRIR título_precio_Cursor;

FETCH title_price_cur-sor INTO title_price_val;

new_price:= "title_price_val.price" * 1.25 INSERTAR EN new_title_price VALORES

(título_precio_val.título, nuevo_precio) CERRAR título_precio_cursor; FIN;

Debido a que este ejemplo usa PL/SQL, no explicaremos gran parte del código en este libro. Sin embargo, el bloque DECLARE muestra claramente la declaración del cursor. En un bloque PL/SQL ejecutable, el cursor se inicializa con el comando OPEN, los valores se recuperan con el comando FETCH y finalmente el cursor se cierra con el comando CLOSE.

La instrucción SELECT es la base del cursor, por lo que es una buena práctica probarla exhaustivamente antes de incluirla en la instrucción DECLARE CURSOR. La declaración SELECT puede operar en la tabla o vista subyacente. Por lo tanto, los cursores de sólo lectura pueden funcionar con vistas no actualizables. Una declaración SELECT puede contener cláusulas como ORDER BY, GROUP BY y HAVING siempre que estas cláusulas no actualicen la tabla fuente. Si el cursor está definido como PARA ACTUALIZAR, se recomienda eliminar dichas cláusulas de la instrucción SELECT.

Los cursores locales se utilizan a menudo como parámetros de salida para procedimientos almacenados. Por lo tanto, puede definir y completar un cursor en un procedimiento almacenado y pasarlo al trabajo por lotes o al procedimiento almacenado que realiza la llamada.

En el siguiente ejemplo sencillo de DB2, declararemos un cursor que busca números de departamento, nombres de departamento y números de administrador en admin_group "XO1".

DECLARAR dept_cursor CURSOR

PARA SELECCIONAR dept_nbr, dept_name, mgr_nbr

DONDE admin_group="X01"

ORDEN POR d"ept_name ASC, dept_nbr DESC, mgr_nbr DESC;

El siguiente ejemplo de Microsoft SQL Server declara y abre un cursor para la tabla de editores. El cursor selecciona el primer registro que coincide con la instrucción SELECT de la tabla de editores y lo inserta en otra tabla. Luego pasa al siguiente registro, luego al siguiente, hasta que se hayan procesado todos los registros. Finalmente, se cierra el cursor y se libera memoria (el comando DEALLOCATE solo se usa en Microsoft SQL Server).

DECLARAR @publisher_name VARCHAR(20)

DECLARAR pub_cursor CURSOR PARA SELECCIONAR pub_name DE los editores DONDE el país "EE.UU."

BUSCAR SIGUIENTE DESDE pub_cursor EN nombre_editor

MIENTRAS @s>FETCH_STATUS=0

INSERTAR EN VALORES de editores_extranjeros("j>nombre_del_editor)

CERRAR pub_cursor DEASIGNAR pub_cursor

En este ejemplo, puede ver el cursor moviéndose a través de un conjunto de registros. (Este ejemplo sólo pretende demostrar la idea, ya que en realidad no existe La mejor manera solución a este problema, es decir, la instrucción INSERT, SELECT.)

SE APLICA A: SQL Server (desde 2008)Base datos SQL Almacén de datos Azure SQLAlmacén de datos paralelo

Define los atributos de un cursor de servidor Transact-SQL, como las propiedades de vista y la consulta utilizada para generar el conjunto de resultados en el que opera el cursor. La instrucción DECLARE CURSOR admite tanto la sintaxis estándar ISO como la sintaxis que utiliza el conjunto de extensiones del lenguaje Transact-SQL.

Sintaxis ISO DECLARAR nombre_cursor [ INSENSITIVO ] [ DESPLAZAMIENTO ] CURSOR PARA declaración_selección [ PARA ( SÓLO LECTURA | ACTUALIZAR [ DE nombre_columna [ ,...n ] ] ) ] [;] Sintaxis extendida de Transact-SQL DECLARAR nombre_cursor CURSOR [ LOCAL | GLOBAL] [FORWARD_ONLY | DESPLAZAMIENTO ] [ ESTÁTICO | JUEGO DE TECLAS | DINÁMICO | FAST_FORWARD ] [LEER_ONLY | SCROLL_LOCKS | OPTIMISTIC ] [ TYPE_WARNING ] FOR select_statement [ FOR UPDATE [ OF column_name [ ,...n ] ] ] [;]

nombre_cursor
nombre_cursor

INSENSIBLE
tempdb; por lo tanto, los cambios en las tablas subyacentes no se reflejan en los datos devueltos por las selecciones de este cursor y este cursor no se puede cambiar. Cuando se utiliza la sintaxis ISO, a menos que se especifique la opción INSENSITIVE, las actualizaciones confirmadas y las eliminaciones realizadas en las tablas base aparecen en selecciones posteriores.

DESPLAZARSE
Indica que todas las opciones de muestreo están disponibles (PRIMERO, ÚLTIMO, ANTERIOR, SIGUIENTE, RELATIVO, ABSOLUTO). Si la instrucción ISO DECLARE CURSOR no especifica una opción SCROLL, solo se admite la opción de recuperación NEXT. La opción SCROLL no se puede especificar con la opción FAST_FORWARD.

declaración_select
Una instrucción SELECT estándar que especifica el conjunto de resultados de un cursor. Las palabras clave FOR BROWSE e INTO no están permitidas en declaración_select declaración del cursor.

declaración_select entra en conflicto con un cursor del tipo solicitado.

SOLO LECTURA

Actualizar ]
nombre_columna [, .. .norte], solo las columnas enumeradas permiten cambios. Si la instrucción UPDATE se utiliza sin una lista de columnas, entonces la actualización es posible para todas las columnas.

nombre_cursor
El nombre Transact-SQL del cursor del servidor específico. nombre_cursor debe seguir las reglas para los identificadores.

LOCAL
Indica que el cursor es local para el paquete, procedimiento almacenado o desencadenador en el que se creó. El nombre del cursor sólo es válido dentro de esta área. Se puede hacer referencia a un cursor mediante variables locales del paquete, procedimientos almacenados, activadores o el parámetro de salida de un procedimiento almacenado. El parámetro OUTPUT se utiliza para pasar un cursor local al paquete, procedimiento almacenado o desencadenador que llama, que luego puede asignar el parámetro a una variable de cursor para el acceso posterior al cursor una vez que se completa el procedimiento almacenado. El cursor se libera implícitamente cuando el lote, el procedimiento almacenado o el desencadenador completa la ejecución, a menos que el cursor se haya pasado al parámetro OUTPUT. Si el cursor se pasó al parámetro SALIDA, el cursor se suelta cuando se liberan todas las variables que hacen referencia a él o cuando se sale del alcance.

GLOBAL
Indica que el cursor es global para la conexión. El nombre del cursor puede ser utilizado por cualquier procedimiento almacenado o paquete que se ejecute en la conexión. El cursor se libera implícitamente sólo si se interrumpe la conexión.

ADELANTE_SÓLO
Especifica que el cursor solo se puede ver desde la primera línea hasta la última. Solo se admite la opción de recuperación FETCH NEXT. Si se especifica FORWARD_ONLY sin las palabras clave STATIC, KEYSET o DYNAMIC, el cursor se comporta como un cursor DYNAMIC. Si no se especifica ni el argumento FORWARD_ONLY ni el argumento SCROLL, el valor predeterminado es el argumento FORWARD_ONLY a menos que estén presentes las palabras clave STATIC, KEYSET o DYNAMIC. Los cursores STATIC, KEYSET y DYNAMIC tienen un valor predeterminado de SCROLL. A diferencia de las API de bases de datos como ODBC y ADO, el modo FORWARD_ONLY es compatible con los siguientes cursores Transact-SQL: STATIC, KEYSET y DYNAMIC.

ESTÁTICO
Define un cursor que crea una copia temporal de los datos para que los utilice el cursor. Todas las consultas al cursor acceden a la tabla temporal especificada en tempdb; por lo tanto, los cambios en las tablas subyacentes no se reflejan en los datos devueltos por las selecciones de este cursor y este cursor no se puede cambiar.

JUEGO DE LLAVES
Indica que la membresía u orden de las filas en el cursor no cambia cuando se abre. Un conjunto de claves que identifican de forma única las filas está integrado en la tabla en tempdb llamado llaves.

Los cambios en los valores que no son clave en las tablas base realizados por el propietario del cursor o confirmados por otros usuarios se muestran cuando el propietario del cursor los ve. Los cambios realizados por otros usuarios no se reflejan (los cambios no se pueden realizar utilizando el cursor del servidor Transact-SQL). Si se elimina una fila, al intentar recuperar filas se devuelve @@FETCH_STATUS -2. Las actualizaciones de los valores clave a través de los límites del cursor son similares a eliminar una fila antigua y luego insertar una nueva. La fila con los nuevos valores no es visible y los intentos de recuperar la fila con los valores antiguos devuelven @@FETCH_STATUS -2. Las actualizaciones son visibles inmediatamente si se realizan a través del cursor usando la cláusula WHERE CURRENT OF.

DINÁMICA
Define un cursor que muestra todos los cambios de datos realizados en las filas del conjunto de resultados mientras se visualiza este cursor. Los valores de los datos, el orden y la pertenencia a filas en cada selección pueden variar. La opción de selección ABSOLUTA no es compatible con cursores dinámicos.

AVANCE RÁPIDO
Indica un cursor FORWARD_ONLY, READ_ONLY que tiene habilitada la optimización del rendimiento. La opción FAST_FORWARD no se puede especificar con las opciones SCROLL o FOR_UPDATE.

SOLO LECTURA
Impide los cambios realizados a través de este cursor. La cláusula WHERE CURRENT OF no puede hacer referencia a un cursor en una instrucción UPDATE o DELETE. Esta opción tiene prioridad sobre la función de actualización del cursor predeterminada.

SCROLL_LOCKS
Indica que se garantiza que las actualizaciones posicionadas o eliminaciones realizadas con el cursor se realizarán correctamente. SQL Server bloquea las filas a medida que se leen en el cursor para garantizar que estén disponibles para cambios posteriores. La opción SCROLL_LOCKS no se puede especificar con la opción FAST_FORWARD o STATIC.

OPTIMISTA
Especifica que las actualizaciones o eliminaciones posicionadas realizadas con el cursor fallarán si la fila se actualizó desde que se leyó en el cursor. SQL Server no bloquea las filas cuando se leen en el cursor. En su lugar se utilizan comparaciones. marca de tiempo valores de columna o sumas de control, si no está en la tabla marca de tiempo columna para determinar si la fila ha cambiado desde que se leyó en el cursor. Si la fila se ha modificado, los intentos de actualizar o eliminar la posición fallarán. La opción OPTIMISTIC no se puede especificar con la opción FAST_FORWARD.

TYPE_WARNING
Especifica que se enviará una advertencia al cliente si el cursor se convierte implícitamente de un tipo solicitado a otro.

declaración_select
Una instrucción SELECT estándar que especifica el conjunto de resultados de un cursor. Las palabras clave COMPUTE, COMPUTE BY, FOR BROWSE e INTO no están permitidas en declaración_select declaración del cursor.

SQL Server convierte implícitamente el cursor a otro tipo si las cláusulas en declaración_select entra en conflicto con un cursor del tipo solicitado. Para obtener más información, consulte Conversiones de cursor implícitas.

PARA ACTUALIZAR]
Define las columnas en el cursor que se actualizarán. Si de nombre_columna [, ... norte], solo las columnas enumeradas permiten cambios. Si la instrucción UPDATE se utiliza sin una lista de columnas, entonces la actualización es posible para todas las columnas a menos que se haya especificado la opción de simultaneidad READ_ONLY.

La instrucción DECLARE CURSOR define atributos de un cursor de servidor Transact-SQL, como las propiedades de vista y la consulta utilizada para generar el conjunto de resultados en el que opera el cursor. La instrucción OPEN completa el conjunto de resultados y la instrucción FETCH devuelve una fila del mismo. La instrucción CLOSE borra el conjunto de resultados actual asociado con el cursor. La declaración DEALLOCATE libera los recursos utilizados por el cursor.

La primera forma de la declaración DECLARE CURSOR utiliza la sintaxis ISO para especificar los parámetros del cursor. La segunda forma de la instrucción DECLARE CURSOR utiliza extensiones del lenguaje Transact-SQL que le permiten definir cursores utilizando los mismos tipos que los utilizados en las funciones de cursor de las API de bases de datos como ODBC y ADO.

Estas dos formas no se pueden mezclar. Si especifica SCROLL u omite palabras clave antes de la palabra clave CURSOR, no podrá utilizar palabras clave entre CURSOR y también para declaración_select palabras clave. Al especificar palabras clave entre el CURSOR, así como para declaración_select palabras clave, no puede especificar SCROLL o INSENSITIVE antes de la palabra clave CURSOR.

Si utiliza la sintaxis Transact-SQL para la instrucción DECLARE CURSOR y no especifica las opciones READ_ONLY, OPTIMISTIC o SCROLL_LOCKS, se supone el siguiente valor predeterminado.

    Si la instrucción SELECT no admite actualizaciones (o tiene permisos insuficientes, o accede a tablas remotas que no admiten actualizaciones, etc.), el cursor se establece en READ_ONLY.

    Los cursores STATIC y FAST_FORWARD están predeterminados en READ_ONLY.

    Los cursores DINÁMICO y KEYSET están predeterminados en OPTIMISTIC.

Sólo otras instrucciones Transact-SQL pueden hacer referencia a los cursores. Las funciones de la API de la base de datos no pueden hacer referencia a cursores. Por ejemplo, una vez declarado un cursor, las funciones y métodos OLE DB, ODBC o ADO no pueden hacer referencia a su nombre. Las filas del cursor no se pueden seleccionar utilizando las funciones y métodos API correspondientes; Para ello, debe utilizar instrucciones FETCH de Transact-SQL.

Los siguientes procedimientos almacenados se pueden utilizar para definir las propiedades de un cursor después de haber sido declarado.

Las variables se pueden utilizar como parte declaración_select, en el que se declara el cursor. Los valores de las variables del cursor no cambian después de su declaración.

De forma predeterminada, los permisos DECLARE CURSOR se otorgan a todos los usuarios que tienen permiso SELECT en las vistas, tablas y columnas utilizadas por el cursor.

No puede utilizar cursores ni activadores en una tabla con un índice de almacén de columnas agrupado. Esta limitación no se aplica a índices no agrupados; Puede utilizar cursores y activadores en una tabla con un índice de almacén de columnas no agrupado.

A. Usar un cursor y una sintaxis simples

El conjunto de resultados creado al abrir este cursor incluye todas las filas y columnas de la tabla. Este cursor se puede actualizar, todas las actualizaciones y eliminaciones están representadas en la selección de este cursor. FETCH``NEXT se recupera solo porque no se especificó el parámetro SCROLL.

DECLARAR vend_cursor CURSOR PARA SELECCIONAR * DE Compras.Vendedor ABRIR vend_cursor FETCH NEXT FROM vend_cursor;

B. Usar cursores anidados para mostrar un informe

El siguiente ejemplo utiliza cursores anidados para mostrar un informe complejo. Se declara un cursor interno para cada proveedor.

ESTABLECER SIN CUENTA EN ; DECLARAR @vendor_id int, @vendor_name nvarchar (50), @message varchar (80), @product nvarchar (50); IMPRIMIR" -------- Informe de productos del proveedor --------"; DECLARAR vendor_cursor CURSOR PARA SELECCIONAR VendorID, Nombre DE Purchasing.Vendor DONDE PreferredVendorStatus = 1 ORDEN POR VendorID; ABRIR vendor_cursor BUSCAR SIGUIENTE DESDE vendor_cursor EN @vendor_id, @vendor_name MIENTRAS @@FETCH_STATUS = 0 COMENZAR IMPRIMIR " " SELECCIONAR @mensaje = "----- Productos del proveedor: "+ @nombre_proveedor IMPRIMIR @mensaje -- Declarar un cursor interno basado -- en seller_id desde el cursor exterior. DECLARAR el cursor_producto CURSOR PARA SELECCIONAR v.Nombre DE Compras.ProductVendor pv, Producción.Producto v DONDE pv.ProductID = v.ProductID AND pv.VendorID = @vendor_id -- Valor variable del cursor exterior ABRIR product_cursor BUSCAR SIGUIENTE DESDE product_cursor EN @product IF @@FETCH_STATUS<>0 IMPRIMIR "<>" WHILE @@FETCH_STATUS = 0 BEGIN SELECT @message = " " + @product PRINT @message FETCH NEXT FROM product_cursor INTO @product END CLOSE product_cursor DEASIGNAR product_cursor - Obtener el siguiente proveedor. FETCH NEXT FROM seller_cursor INTO @vendor_id, @vendor_name FIN CERRAR proveedor_cursor; DEALLOCATE proveedor_cursor;


El cursor es un enlace al área de memoria contextual. En algunas implementaciones del lenguaje de programación SQL (Oracle, Microsoft SQL Server): el conjunto de resultados obtenido al ejecutar una consulta y el puntero del registro actual asociado a ella. Yo diría que un cursor es una tabla virtual que representa un almacenamiento de datos alternativo. En este caso, el cursor le permite acceder a sus datos como si fueran datos de una matriz normal.
Los cursores se utilizan en procedimientos almacenados. Basta de teoría, veamos un ejemplo:
Tenemos una base de datos (la base de datos no es buena, esta es una de mis trabajo de laboratorio, pero nuestro profesor de bases de datos insistió en tal estructura)
/*información bancaria*/
CREAR TABLA `banco` (

`BankName` VARCHAR (50) COLLATE utf8_bin NOT NULL DEFAULT "",


CLAVE PRINCIPAL (`BankId`)

)MOTOR=InnoDB
CONJUNTO DE CARACTERES "utf8" COLABORAR "utf8_bin";
/*datos sobre depósitos */
CREAR TABLA `distribución bancaria` (
`BankId` ENTERO (11) NO NULO,
`Persent` INTEGER (11) POR DEFECTO NULO,
`ContributeAmount` DECIMAL (10,0) NO NULO,
`ClientId` ENTERO (11) NO NULO,
CLAVE PRIMARIA(`BankId`, `ClientId`),
CLAVE `BankId` (`BankId`),
CLAVE `ClienteId` (`ClienteId`),
RESTRICCIÓN `bankdistribution_fk` CLAVE EXTRANJERA (`BankId`) REFERENCIAS `bank` (`BankId`),
RESTRICCIÓN `bankdistribution_fk1` CLAVE EXTRANJERA (`ClientId`) REFERENCIAS `cliente` (`ClientId`)
)MOTOR=InnoDB
/*datos sobre inversores*/
CREAR TABLA `cliente` (
`ClientId` INTEGER (3) NO NULO AUTO_INCREMENT,
`CreditCardId` BIGINT(10) NO NULO,
`Apellido` VARCHAR (50) COLLATE utf8_bin NOT NULL DEFAULT "",
`Nombre` VARCHAR (50) COLLATE utf8_bin NOT NULL DEFAULT "",
`FirstName` VARCHAR (50) COLLATE utf8_bin NOT NULL DEFAULT "",
`Teléfono` VARCHAR (50) COLLATE utf8_bin NOT NULL DEFAULT "",
`Dirección` VARCHAR (50) COLLATE utf8_bin NOT NULL DEFAULT "",
`SafeId` ENTERO (5) NO NULO,
CLAVE PRIMARIA(`ClientId`, `CreditCardId`),
CLAVE `ClienteId` (`ClienteId`)

)MOTOR=InnoDB
AUTO_INCREMENT=11 CONJUNTO DE CARACTERES "utf8" COLABORAR "utf8_bin"

Digamos que necesitamos recibir cada banco por turno y realizar algunas acciones con él, la siguiente consulta podría ayudarnos con esto

Seleccione `banco`.* DESDE `banco` LÍMITE DE NÚMERO DEL_RECORD_NECESITAMOS,1
. Así, usando LIMIT WE NEED_RECORD NUMBER, 1, extraemos cada registro en un ciclo de la tabla del banco por turno y realizamos las acciones que necesitamos con él, mientras aumentamos el valor de WE NEED_RECORD NUMBER en 1. Ahora haremos lo mismo pero usando un cursor
Comenzar
/*variables donde extraemos datos */
Declarar vBankId entero;
Declarar vBankName VARCHAR(50);
Declarar vAddress VARCHAR(50);
Declarar vPhone VARCHAR (50);
/* variable hadler - a*/
Declarar hecho entero predeterminado 0;
/*Declaración del cursor*/
Declare el cursor BankCursor para seleccionar `banco`.`BankId`,`bank`.`BankName`,`bank`.`Address`,`bank`.`Phone`, FROM `bank` donde 1;
/*Propósito del MANEJADOR, que se explicará a continuación*/
DECLARAR CONTINUAR MANEJADOR PARA SQLSTATE "02000" SET done=1;
/* abrir cursor */
Cursor de banco abierto;
/*recuperar datos*/
MIENTRAS haya terminado = 0 HACER

tomamos las acciones que necesitamos
FINALIZAR MIENTRAS;
/*cerrando el cursor*/
Cerrar cursor bancario;
FIN ;

* Este código fuente fue resaltado con Resaltador de código fuente.

Error: 1329 ESTADO SQL: 02000 (ER_SP_FETCH_NO_DATA)

Mensaje: Sin datos: cero filas recuperadas, seleccionadas o procesadas

SQLSTATE: 02000 se activa cuando se alcanza el final del cursor o cuando seleccionar o actualizar devuelve una cadena vacía.

En la siguiente línea declaramos el cursor DECLARE cursor_name CURSOR FOR select_statement;
Abrir el cursor Abrir cursor_name;
Luego, hasta llegar al final del cursor (WHILE done = 0 DO), extraemos los datos y los procesamos.
Debe cerrar el cursor antes de salir del procedimiento almacenado. Cerrar nombre_cursor;

No parece complicado. Pero hay muchos peligros asociados con SQLSTATE "02000".

MIENTRAS haya terminado = 0 HACER
FETCH BankCursor INTO vBankId, vBankName, vAddress, vPhone;

Seleccione (ContributeAmount) EN vContributeAmountSUM FROM bankdistribution donde BankId = vBankId límite 1;
hacemos algunas acciones
FINALIZAR MIENTRAS;

* Este código fuente fue resaltado con Resaltador de código fuente.


Todo está bien y correcto desde el punto de vista de la sintaxis. Pero desde un punto de vista lógico, no. Puede suceder que los depositantes no hayan abierto cuentas en algún banco, entonces para Seleccionar (ContributeAmount) INTO vContributeAmountSUM FROM distribución bancaria donde BankId = vBankId límite 1; Se activará SQLSTATE: 02000, la variable done se establecerá en 1 y el ciclo while finalizará antes de lo esperado. Esto se puede evitar haciendo lo siguiente
MIENTRAS haya terminado = 0 HACER
FETCH BankCursor INTO vBankId, vBankName, vAddress, vPhone;
/* extraer para el banco el importe de cualquiera de sus depósitos */


si (vContributeAmountSUM > 0) entonces
/* extraer para el banco el importe de cualquiera de sus depósitos */

terminara si ;
hacemos algunas acciones
FINALIZAR MIENTRAS;

* Este código fuente fue resaltado con Resaltador de código fuente.


Con la primera solicitud, verificamos si hay contribuciones (si no hay ninguna, entonces vContributeAmountSUM == 0) y solo si las hay, recuperamos los datos.

Ahora digamos que necesitamos eliminar el monto total en cuentas en diferentes bancos para cada cliente.
Declarar el cursor ClientSummCursor para seleccionar suma

Declare el cursor ClientSummCursor para la suma seleccionada (`bankdistribution`.`ContributeAmount`), `bankdistribution`.`ClientId` FROM `bankdistribution` Interna Únase al cliente en (client.ClientId = bankdistribution.`ClientId`) donde 1 grupo por `bankdistribution`. `IdCliente`;

Abra ClientSummCursor;
MIENTRAS haya terminado = 0 HACER
FETCH BankCursor INTO vBankId, vBankName, vAddress, vPhone;
/* extraer para el banco el importe de cualquiera de sus depósitos */
Seleccione Count(ContributeAmount) INTO vContributeAmountSUM FROM bankdistribution donde BankId = vBankId límite 1;
/* comprobamos si realmente hay depósitos en este banco */
si (vContributeAmountSUM > 0) entonces
/* extraer para el banco el importe de cualquiera de sus depósitos */
Seleccione ContributeAmount INTO vContributeAmountSUM FROM bankdistribution donde BankId = vBankId límite 1;
terminara si ;


hacemos algunas acciones.
FINALIZAR MIENTRAS;

* Este código fuente fue resaltado con Resaltador de código fuente.

La misma situación puede surgir cuando los datos en el cursor ClientSummCursor terminan antes que los datos en BankCursor, se activa SQLSTATE: 02000, la variable done se establece en 1 y el ciclo while termina antes de lo esperado. Esto se puede evitar haciendo lo siguiente

Abra ClientSummCursor;
MIENTRAS haya terminado = 0 HACER
FETCH BankCursor INTO vBankId, vBankName, vAddress, vPhone;
/* extraer para el banco el importe de cualquiera de sus depósitos */
Seleccione Count(ContributeAmount) INTO vContributeAmountSUM FROM bankdistribution donde BankId = vBankId límite 1;
/* comprobamos si realmente hay depósitos en este banco */
si (vContributeAmountSUM > 0) entonces
/* extraer para el banco el importe de cualquiera de sus depósitos */
Seleccione ContributeAmount INTO vContributeAmountSUM FROM bankdistribution donde BankId = vBankId límite 1;
terminara si ;
/* antes de extraer datos del segundo cursor, recuerde el estado de sqlstate */
SET old_status = hecho;
/* extraemos los datos que necesitamos */
FETCH ClientSummCursor EN vSum,vClientId;
/* comprobar si se recuperaron los datos y si sqlstate 0200 falló */
si (hecho = 0) entonces
hacemos algunas acciones.
terminara si ;
/* antes de que finalice el while, restaura el valor de la variable hecha */
conjunto hecho = old_status;
FINALIZAR MIENTRAS;

* Este código fuente fue resaltado con Resaltador de código fuente.

Gracias a todos los que han leído hasta aquí, espero que esto sea útil para alguien.

La implementación de un cursor en una base de datos se asemeja a una clase Java que tiene un conjunto de datos y métodos para procesarlos. Donde cursor sql utiliza los datos como una matriz regular. Los cursores se pueden utilizar en activadores, procedimientos almacenados y funciones.

De acuerdo con el estándar SQL, cuando se trabaja con cursores, se realizan las siguientes acciones básicas:

  • declaración de cursor;
  • abrir un cursor con datos de lectura;
  • muestreo línea por línea de datos del cursor;
  • cambiar los datos de la fila usando el cursor;
  • cerrar el cursor, después de lo cual se vuelve inaccesible;
  • soltando el cursor, es decir eliminar un cursor de la memoria porque cerrarlo no necesariamente libera la memoria asociada a él.

En diferentes implementaciones la definición cursor puede tener algunas diferencias. Por ejemplo, a veces es necesario liberar explícitamente la memoria asignada a un cursor. Una vez liberado el cursor, también se libera la memoria asociada a él. Esto hace posible reutilizar el nombre del cursor. En otras implementaciones, cuando se cierra el cursor, la memoria se libera implícitamente.

En algunos casos, no puede prescindir de utilizar un cursor. Sin embargo, si es posible, debe evitar el uso de un cursor y trabajar con comandos de procesamiento de datos estándar: SELECCIONAR, ACTUALIZAR, INSERTAR, ELIMINAR. Esto se debe al hecho de que los cursores no permiten operaciones de modificación en todo el volumen de datos y la velocidad de realizar operaciones de procesamiento de datos utilizando un cursor es notablemente menor que la de medios estándar SQL.

Si un programa puede cambiar los datos cargados en el cursor, entonces se llama modificable. Cuando hablamos de cursores, no debemos olvidarnos del aislamiento de transacciones. Un usuario modifica un registro usando un cursor, mientras que otro usuario lee ese registro usando su propio cursor. Además, puede cambiar el mismo registro, lo que hace necesario mantener la integridad de los datos.

Declarando un cursor

Los cursores deben declararse antes de poder usarse. El estándar SQL utiliza la siguiente sintaxis para crear un cursor:

Declarar cursor_nombre_cursor para select_statement ])]

Esta expresión declara un cursor. declarar cursor con el nombre "cursor_name".

INSENSIBLE Se crea un cursor estático que no permite realizar cambios. Además, no se muestran los cambios realizados por otros usuarios. Si falta la palabra clave INSENSITIVE, se crea un cursor dinámico.

Cuando se utiliza una palabra clave DESPLAZARSE el cursor creado se puede desplazar en cualquier dirección, lo que le permite aplicar cualquier comando de selección. Si se omite este argumento, entonces el cursor será secuencial, es decir. su visualización sólo será posible en una dirección: de principio a fin.

Expresión declaración_select Indica una estructura para leer información como seleccionar... de.... No debe contener el operador. en, ya que el cursor tiene su propio operador buscar para llenar variables con datos del cursor.

Al especificar un argumento PARA SÓLO LECTURA Se creará un cursor de solo lectura y no se permitirán modificaciones en los datos. Un cursor dinámico se puede declarar como cursor de solo lectura, lo que permite mostrar los cambios realizados por otro usuario.

Creando un cursor con un argumento PARA ACTUALIZAR le permite realizar cambios en los datos en el cursor, ya sea en columnas especificadas o, en ausencia de un argumento DE nombre_columna, en todas las columnas.

Puede declarar varios cursores en una subrutina. Pero cada cursor debe tener un nombre único. Para abrir un cursor debes usar el operador abierto que abre el cursor previamente declarado:

Cursor abierto

SQL define la siguiente sintaxis para abrir un cursor "cursor open":

Abrir nombre_cursor;

Obteniendo datos de un cursor, búsqueda de cursor

La sintaxis para leer datos de un cursor en algunas variables es la siguiente:

Obtener nombre_cursor en nombre_var [, nombre_var] ...;

Operador buscar selecciona los datos abiertos del cursor en variables ubicadas después en y mueve el cursor a la siguiente posición.

Cierre del cursor

Operador cerca cierra el cursor. Si el operador no se especifica explícitamente, el cursor se cierra automáticamente al cerrar el bloque de programa correspondiente.

Cerrar nombre_cursor;

Después de cerrar, el cursor se vuelve inaccesible. Al cerrar, se liberan todos los bloqueos instalados mientras el cursor estaba en funcionamiento. Sólo se pueden cerrar los cursores abiertos. Se puede volver a abrir un cursor cerrado pero no liberado. No está permitido cerrar un cursor no abierto.

Cada DBMS tiene sus propias peculiaridades en el uso de un cursor.

Características del uso de cursores en Oracle.

Hay cuatro atributos de cursor en PL/SQL %ENCONTRÓ, %EXTRAVIADO, %ESTA ABIERTO Y %NÚMERO DE FILAS. Los atributos del cursor se declaran como los operadores %TYPE y %ROWTYPE, a la derecha del nombre del cursor.

Atributo %ENCONTRADO

Atributo %NO ENCONTRADO

El atributo %NOTFOUND es exactamente lo opuesto a %FOUND.

Atributo %ISOPEN

El atributo %ISOPEN sólo indica si el cursor está abierto o no.

Atributo %ROWCOUNT

Atributo %NÚMERO DE FILAS es un atributo numérico que devuelve el número de filas leídas por el cursor en un momento determinado.

Ejemplo de un cursor SQL en un DBMS Oracle

Declarar v_id managers.id %TYPE; v_nombre administradores.nombre%TIPO; v_comm managers.comm%TIPO; cursor crs para seleccionar id, nombre, suma (comunicación) como comunicación de los administradores donde los datos entre "2014-11-01" y "2014-11-30" se agrupan por id, nombre; comenzar crs abiertos; bucle SALIR CUANDO crs%NOTFOUND; FETCH crs en v_id, v_name, v_comm; insertar en valores de bonificación (id, nombre, comunicación) (crs.id, crs.name, crs.comm); bucle final; comprometerse; cerrar crs; fin;

Características del uso de cursores en el servidor SQL.

Los cursores utilizados en MSSQL pueden ser secuenciales o desplazables. Secuencial le permite seleccionar datos en una sola dirección: de principio a fin. Los cursores desplazables permiten el movimiento en ambas direcciones y le permiten saltar a una fila arbitraria en el conjunto de resultados del cursor.

SQL Server admite cursores estáticos, dinámicos, secuenciales y controlados por conjuntos de claves.

En un diseño de cursor estático, la información se almacena como una instantánea en algún momento. Por lo tanto, los cambios realizados en la base de datos por otro usuario no son visibles. Mientras se abre el cursor, el servidor bloquea todas las filas incluidas en su conjunto de resultados completo. Un cursor estático no cambia después de su creación y siempre muestra el conjunto de datos que existía en el momento de su apertura. Si otros usuarios cambian los datos incluidos en el cursor de la tabla fuente, esto no afectará al cursor estático. Es imposible realizar cambios en un cursor estático, por lo que siempre se abre en modo de solo lectura.

Un cursor dinámico requiere recursos de software y sobrecarga de red adicionales. Cuando se utilizan cursores dinámicos, no se crea una copia completa de los datos, pero las selecciones de las tablas de origen se realizan solo cuando el usuario accede a ciertos datos. Durante la recuperación, el servidor bloquea las filas y cualquier cambio que el usuario realice en el conjunto de resultados completo del cursor será visible en el cursor. Sin embargo, una vez que el cursor haya obtenido datos, los cambios realizados por otro usuario ya no se reflejarán en el cursor.

Un cursor controlado por un conjunto de teclas tiene propiedades entre estáticas y dinámicas. Los registros se identifican en el momento del muestreo y, por lo tanto, se realiza un seguimiento de los cambios. Este tipo de cursor es útil al implementar el desplazamiento hacia atrás. En este caso, las adiciones y eliminaciones de datos no son visibles hasta que la información se actualiza y el cursor selecciona nueva versión registros si se han realizado cambios en ellos.

Los cursores estáticos se utilizan mejor para sistemas de procesamiento de información, es decir. para sistemas de información o para fines estadísticos y analíticos. Un cursor estático es mejor para recuperar grandes cantidades de datos. En los sistemas de compra o reserva electrónica de objetos (asientos, billetes), es necesario percibir dinámicamente información actualizada a medida que se realizan cambios. En tales casos, se utiliza un cursor dinámico. En estas aplicaciones, la cantidad de datos transferidos suele ser pequeña y se accede a ellos a nivel de registro individual.

Los cursores secuenciales no permiten recuperar datos en dirección inversa, solo desde el principio hasta el final del cursor. Un cursor secuencial no almacena un conjunto de todas las filas de datos. Se leen de la base de datos tan pronto como se realiza una selección en el cursor, lo que permite reflejar dinámicamente todos los cambios realizados por los usuarios en la base de datos mediante los comandos INSERTAR, ACTUALIZAR, ELIMINAR. El cursor lee el estado de datos más reciente.

Declaración del cursor

Declarar cursor_nombre del cursor para SELECT_statement ]]

Cuando se utiliza una palabra clave LOCAL Se creará un cursor local que será visible solo dentro del bloque, disparador, procedimiento almacenado o función definida por el usuario. Palabra clave GLOBAL, define un cursor global que existe hasta que se cierra la conexión actual.

Operador ADELANTE_SÓLO define un cursor secuencial que permite recuperar datos solo en la dirección desde la primera fila hasta la última. Cuando se utiliza el operador DESPLAZARSE Se crea un cursor desplazable que permite acceder a los datos en cualquier orden y en cualquier dirección.

El tipo de cursor lo determinan los operadores:

  • ESTÁTICO: creación de un cursor estático;
  • DINÁMICO: creación de un cursor dinámico;
  • KEYSET: creación de un cursor de tecla.

Si para cursor SOLO LECTURA especificar argumento AVANCE RÁPIDO, entonces el cursor creado se optimizará para acceso rapido a los datos. Este argumento no se puede utilizar junto con argumentos. ADELANTE_SÓLO Y OPTIMISTA.

Si el cursor se crea con el operador OPTIMISTA, entonces está prohibido cambiar o eliminar filas que se cambiaron después de abrir el cursor.

Al especificar un argumento TYPE_WARNING el servidor informará un cambio de tipo de cursor implícito si es incompatible con la consulta SELECT.

Recuperar datos de un cursor, buscar

Inmediatamente después de abrir el cursor, puede obtener su contenido usando el siguiente comando:

Cuando se utiliza el operador PRIMERO Se devolverá la primera fila del conjunto de resultados del cursor, que se convierte en la fila actual. Cuando se especifica ÚLTIMO se devolverá la última línea del cursor. También se convierte en la línea actual.

Al especificar un operador PRÓXIMO Se devolverá la fila inmediatamente después de la actual en el conjunto de resultados. Esta línea se convierte en la línea actual. Comando predeterminado BUSCAR utiliza exactamente este método para recuperar filas.

Al especificar un operador PREVIO se devolverá la línea anterior a la actual. Esta línea se convierte en la línea actual.

Operador ABSOLUTO (número_línea | @número_línea_variable) devuelve una fila por su número ordinal absoluto en el conjunto de resultados completo del cursor. El número de línea se puede especificar mediante una constante o como el nombre de una variable en la que se almacena el número de línea. La variable debe ser un tipo de datos entero. Se indican valores tanto positivos como negativos. Al especificar un valor positivo, la cadena se cuenta desde el principio del conjunto, mientras que un valor negativo se cuenta desde el final. La línea seleccionada se convierte en la línea actual. Si se especifica un valor nulo, no se devuelve ninguna fila.

Argumento RELATIVO (número de filas | @variable número de filas) devuelve la línea desplazada el número especificado de líneas después de la actual. Si especifica un número negativo de filas, se devolverá la fila que tenga el número de filas especificado antes de la actual. Al especificar un valor nulo se devolverá la fila actual. La fila devuelta se convierte en la fila actual.

Para abrir un cursor global, debe especificar una palabra clave antes de su nombre GLOBAL. El nombre del cursor también se puede especificar mediante una variable.

en expresión EN @nombre_variable [,...n] Se define una lista de variables en la que se almacenarán los valores de columna correspondientes de la fila devuelta. El orden de las variables debe coincidir con el orden de las columnas en el cursor y el tipo de datos de la variable debe coincidir con el tipo de datos en la columna del cursor.

Cambiar y eliminar datos usando un cursor

Para cambiar datos usando un cursor, debe emitir un comando ACTUALIZAR en el siguiente formato:

En una operación se pueden cambiar los valores de varias columnas de la fila actual del cursor, pero todas deben pertenecer a la misma tabla.

Para eliminar datos usando un cursor, use el comando ELIMINAR en el siguiente formato:

Como resultado, se eliminará la línea actual en el cursor.

Liberar memoria, desasignar

Para eliminar un cursor de la memoria, use el comando

Desasignar nombre_cursor;

@@FETCH_STATUS atributo

Para determinar la presencia de filas en el cursor, debe utilizar una variable global @@FETCH_STATUS, que toma un valor distinto de cero si no hay más filas en el cursor. Si el conjunto de filas aún no se ha agotado, entonces @@FETCH_STATUS es igual a cero.

Ejemplo de un cursor en el servidor SQL

Declare @company varchar(50), @manager varchar(50), @message varchar(256); declarar el cursor crs_clients local para la empresa seleccionada, gerente de clientes donde ciudad = "Moscú" ordenar por empresa, gerente; imprimir "Lista de clientes"; abrir crs_clients; buscar siguiente desde crs_clients a @company, @manager; mientras que @@FETCH_STATUS = 0 comienza a seleccionar @message = "Empresa " + @empresa + " gerente " + @manager; imprimir @mensaje; -- pasar al siguiente registro y buscar siguiente desde crs_clients a @company, @manager; fin; cerrar crs_clients; desasignar crs_clients;

Se da la definición del cursor. Se proporciona una descripción de sus tipos y comportamiento: cursores estáticos, dinámicos, secuenciales y de teclas. Se describen los principios del control del cursor: crear y abrir un cursor, leer datos, cerrar un cursor. Se dan ejemplos de programación de cursores.

Concepto de cursor

Una consulta a una base de datos relacional normalmente devuelve varias filas (registros) de datos, pero la aplicación solo procesa un registro a la vez. Incluso si se trata de varias filas al mismo tiempo (por ejemplo, mostrando datos en forma de hojas de cálculo), su número sigue siendo limitado. Además, al modificar, eliminar o agregar datos, la unidad de trabajo es la serie. En esta situación, el concepto de cursor pasa a primer plano y, en este contexto, el cursor es un puntero a una fila.

Un cursor en SQL es un área en la memoria de la base de datos que está diseñada para contener la última declaración SQL. Si la declaración actual es una consulta de base de datos, también se almacena en la memoria una fila de datos de consulta llamada valor actual o línea de cursor actual. El área especificada en la memoria tiene un nombre y es accesible para los programas de aplicación.

Normalmente, los cursores se utilizan para seleccionar de una base de datos un subconjunto de la información almacenada en ella. En cualquier momento dado, el programa de aplicación puede comprobar una línea del cursor. Los cursores se utilizan a menudo en declaraciones SQL, integrado en programas de aplicación escritos en lenguajes de procedimiento. Algunos de ellos son creados implícitamente por el servidor de la base de datos, mientras que otros los definen los programadores.

De acuerdo con el estándar SQL, cuando se trabaja con cursores, se pueden distinguir las siguientes acciones principales:

  • creación o declaración del cursor;
  • cursor de apertura, es decir. llenarlo con datos almacenados en una memoria multinivel;
  • selección del cursor y cambiar filas de datos con él;
  • cerrando el cursor, después de lo cual se vuelve inaccesible para los programas de usuario;
  • liberando el cursor, es decir. eliminar el cursor como objeto porque cerrarlo no necesariamente libera la memoria asociada a él.

La definición de un cursor puede variar ligeramente entre implementaciones. Por ejemplo, a veces un desarrollador debe liberar explícitamente la memoria asignada para un cursor. Después suelta el cursor su memoria asociada también se libera. Esto hace posible reutilizar su nombre. En otras implementaciones cuando cerrando el cursor La liberación de memoria ocurre implícitamente. Inmediatamente después de la recuperación, queda disponible para otras operaciones: abriendo otro cursor etc.

En algunos casos, es inevitable utilizar un cursor. Sin embargo, si es posible, esto debe evitarse y trabajar con comandos de procesamiento de datos estándar: SELECCIONAR, ACTUALIZAR, INSERTAR, ELIMINAR. Además del hecho de que los cursores no permiten operaciones de modificación en todo el volumen de datos, la velocidad de realizar operaciones de procesamiento de datos utilizando un cursor es notablemente menor que la de las herramientas SQL estándar.

Implementación de cursores en entorno MS SQL Server.

SQL Server admite tres tipos de cursores:

  • Los cursores SQL se utilizan principalmente en activadores, procedimientos almacenados y scripts;
  • los cursores del servidor operan en el servidor e implementan la interfaz de programación de aplicaciones para ODBC, OLE DB, DB_Library;
  • Los cursores del cliente se implementan en el propio cliente. Obtienen todo el conjunto de filas de resultados del servidor y lo almacenan localmente, lo que acelera el procesamiento de datos al reducir el tiempo perdido en las operaciones de red.

Los diferentes tipos de aplicaciones multiusuario requieren diferentes tipos de acceso paralelo a los datos. Algunas aplicaciones requieren acceso inmediato a información sobre cambios en la base de datos. Esto es típico de los sistemas de reserva de billetes. En otros casos, como los sistemas de informes estadísticos, la estabilidad de los datos es importante porque si se modifican constantemente, los programas no podrán mostrar la información de manera efectiva. Diferentes aplicaciones necesitan diferentes implementaciones de cursores.

En SQL Server, los tipos de cursor varían en las capacidades que brindan. El tipo de cursor se determina en la etapa de su creación y no se puede cambiar. Algunos tipos de cursores pueden detectar cambios realizados por otros usuarios en las filas incluidas en el conjunto de resultados. Sin embargo, SQL Server solo rastrea los cambios en dichas filas mientras se accede a la fila y no permite que se modifiquen los cambios una vez que la fila ya se ha leído.

Los cursores se dividen en dos categorías: secuencial y desplazable. Consecutivo le permite seleccionar datos en una sola dirección: de principio a fin. Cursores desplazables proporcionan una mayor libertad de acción: es posible moverse en ambas direcciones y saltar a una fila arbitraria del conjunto de resultados del cursor. Si el programa puede modificar los datos a los que apunta el cursor, se llama desplazable y modificable. Hablando de cursores, no debemos olvidarnos del aislamiento de transacciones. Cuando un usuario modifica un registro, otro lo lee usando su propio cursor y además puede modificar el mismo registro, lo que hace necesario mantener la integridad de los datos.

SQL Server admite estática, dinámica, secuencial y controlado por un juego de llaves.

En el esquema con cursor estático la información se lee de la base de datos una vez y se almacena como una instantánea (en algún momento), por lo que los cambios realizados en la base de datos por otro usuario no son visibles. Por un momento abriendo el cursor el servidor establece un bloqueo en todas las filas incluidas en su conjunto de resultados completo. Cursor estático no cambia después de la creación y siempre muestra el conjunto de datos que existía en el momento de su apertura.

Si otros usuarios cambian los datos incluidos en el cursor en la tabla fuente, esto no afectará la cursor estático.

EN cursor estático No es posible realizar cambios, por lo que siempre se abre en modo de solo lectura.

Cursor dinámico mantiene los datos en un estado "activo", pero esto requiere recursos de red y software. Usando cursores dinámicos No se crea una copia completa de los datos de origen, pero se realiza una selección dinámica de las tablas de origen solo cuando el usuario accede a ciertos datos. Durante la recuperación, el servidor bloquea las filas y cualquier cambio que el usuario realice en el conjunto de resultados completo del cursor será visible en el cursor. Sin embargo, si otro usuario ha realizado cambios después de que el cursor haya obtenido los datos, no se reflejarán en el cursor.

Cursor controlado por un conjunto de teclas., está en el medio entre estos extremos. Los registros se identifican en el momento del muestreo y, por tanto, se realiza un seguimiento de los cambios. Este tipo de cursor es útil al implementar el desplazamiento hacia atrás; luego, las adiciones y eliminaciones de filas no son visibles hasta que se actualiza la información y el controlador selecciona una nueva versión del registro si se le han realizado cambios.

Cursores secuenciales no se les permite recuperar datos en la dirección inversa. El usuario sólo puede seleccionar filas desde el principio hasta el final del cursor. Cursor en serie no almacena un conjunto de todas las filas. Se leen de la base de datos tan pronto como se seleccionan en el cursor, lo que permite que todos los cambios realizados por los usuarios en la base de datos se reflejen dinámicamente mediante los comandos INSERTAR, ACTUALIZAR, ELIMINAR. El cursor muestra el estado más reciente de los datos.

Cursores estáticos Proporcionar una visión estable de los datos. Son buenos para sistemas de "almacenamiento" de información: aplicaciones para sistemas de informes o con fines estadísticos y analíticos. Además, cursor estático se adapta mejor que otros al muestreo de grandes cantidades de datos. Por el contrario, los sistemas electrónicos de compra o reserva de billetes requieren una percepción dinámica de información actualizada a medida que se realizan cambios. En tales casos se utiliza cursor dinámico. En estas aplicaciones, la cantidad de datos transferidos suele ser pequeña y se accede a ellos a nivel de fila (registro individual). El acceso grupal es muy raro.

Gestión de cursores en entorno MS SQL Server

control del cursor implementado ejecutando los siguientes comandos:

  • DECLARAR - creación o declaración del cursor;
  • ABIERTO - cursor de apertura, es decir. llenarlo con datos;
  • BUSCAR selección del cursor y cambiar filas de datos usando el cursor;
  • CERCA - cerrando el cursor;
  • DESASIGNAR – liberando el cursor, es decir. eliminando el cursor como un objeto.

Declaración del cursor

El estándar SQL proporciona el siguiente comando para crear un cursor:

El uso de la palabra clave INSENSITIVE creará cursor estático. Cambios de datos No están permitidos, además, no se muestran los cambios realizados por otros usuarios. Si falta la palabra clave INSENSITIVE, se cursor dinámico.

Cuando especifica la palabra clave SCROLL, el cursor creado se puede desplazar en cualquier dirección, lo que le permite utilizar cualquier comando de selección. Si se omite este argumento, el cursor será coherente, es decir. su visualización sólo será posible en una dirección: de principio a fin.

La instrucción SELECT especifica el cuerpo de la solicitud SELECT, que determina el conjunto de filas resultante para el cursor.

Al especificar FOR READ_ONLY se crea un cursor de solo lectura y no se permite ninguna modificación de los datos. Se diferencia de la estática, aunque esta última tampoco permite cambiar datos. Puede declararse como un cursor de solo lectura. cursor dinámico, lo que permitirá mostrar los cambios realizados por otro usuario.

Crear un cursor con un argumento FOR UPDATE le permite ejecutar en el cursor cambio de datos ya sea en las columnas especificadas o, en ausencia del argumento OF nombre_columna, en todas las columnas.

En el entorno de MS SQL Server, se acepta la siguiente sintaxis para el comando de creación del cursor:

<создание_курсора>::= DECLARAR nombre_cursor CURSOR PARA SELECT_statement ]]

El uso de la palabra clave LOCAL creará un cursor local que es visible solo dentro del alcance del paquete, disparador, procedimiento almacenado o función definida por el usuario que lo creó. Cuando finaliza un paquete, desencadenador, procedimiento o función, el cursor se destruye implícitamente. Para pasar el contenido del cursor fuera de la construcción que lo creó, debe asignar un argumento de SALIDA a su parámetro.

Si se especifica la palabra clave GLOBAL, se crea un cursor global; existe hasta que se cierra la conexión actual.

Al especificar FORWARD_ONLY se crea cursor en serie; Los datos solo se pueden muestrear en la dirección desde la primera fila hasta la última.

Al especificar SCROLL se crea cursor desplazable; Se puede acceder a los datos en cualquier orden y en cualquier dirección.

Al especificar STATIC se crea cursor estático.

Al especificar KEYSET se crea un cursor de clave.

Al especificar DYNAMIC se crea cursor dinámico.

Si especifica el argumento FAST_FORWARD para un cursor READ_ONLY, el cursor creado se optimizará para un acceso rápido a los datos. Este argumento no se puede utilizar junto con los argumentos FORWARD_ONLY u OPTIMISTIC.

Un cursor creado con el argumento OPTIMISTIC evita la modificación o eliminación de filas que se modificaron después abriendo el cursor.

Al especificar el argumento TYPE_WARNING, el servidor informará al usuario de un cambio implícito en el tipo de cursor si es incompatible con la consulta SELECT.

Abriendo el cursor

Para abriendo el cursor y llenándolo con datos de la consulta SELECT especificada al crear el cursor, use el siguiente comando:

Después abriendo el cursor Se ejecuta la instrucción SELECT asociada, cuya salida se almacena en la memoria multinivel.

Recuperar datos de un cursor

Justo después de abriendo el cursor puedes seleccionar su contenido (el resultado de ejecutar la consulta correspondiente) usando el siguiente comando:

Al especificar PRIMERO se devolverá la primera fila del conjunto de resultados completo del cursor, que se convierte en la fila actual.

Al especificar ÚLTIMO se devuelve la fila más reciente del cursor. También se convierte en la línea actual.

Al especificar SIGUIENTE se devuelve la fila inmediatamente después de la actual en el conjunto de resultados completo. Ahora se vuelve actual. De forma predeterminada, el comando FETCH utiliza este método para recuperar filas.

La palabra clave PRIOR devuelve la fila anterior a la actual. Se vuelve actual.

Argumento ABSOLUTO (número_línea | @número_línea_variable) devuelve una fila por su número ordinal absoluto en el conjunto de resultados completo del cursor. El número de línea se puede especificar mediante una constante o como el nombre de una variable en la que se almacena el número de línea. La variable debe ser un tipo de datos entero. Se indican valores tanto positivos como negativos. Al especificar un valor positivo, la cadena se cuenta desde el principio del conjunto, mientras que un valor negativo se cuenta desde el final. La línea seleccionada se convierte en la línea actual. Si se especifica un valor nulo, no se devuelve ninguna fila.

Argumento RELATIVO (número de filas | @variable número de filas) devuelve la línea que es el número especificado de líneas después de la actual. Si especifica un número negativo de filas, se devolverá la fila que tenga el número de filas especificado antes de la actual. Al especificar un valor nulo se devolverá la fila actual. La fila devuelta se convierte en la fila actual.

A abrir cursor global, debe especificar la palabra clave GLOBAL antes de su nombre. El nombre del cursor también se puede especificar mediante una variable.

en diseño EN @nombre_variable [,...n] Se especifica una lista de variables en las que se almacenarán los valores de columna correspondientes de la fila devuelta. El orden de especificación de las variables debe coincidir con el orden de las columnas en el cursor y el tipo de datos de la variable debe coincidir con el tipo de datos en la columna del cursor. Si no se especifica la construcción INTO, entonces el comportamiento del comando FETCH se parecerá al comportamiento del comando SELECT: los datos se muestran en la pantalla.

Cambiar y eliminar datos

Para realizar cambios utilizando un cursor, debe emitir un comando ACTUALIZAR en el siguiente formato:

Se pueden cambiar varias columnas de la fila actual del cursor en una sola operación, pero todas deben pertenecer a la misma tabla.

Para eliminar datos usando un cursor, use el comando ELIMINAR en el siguiente formato:

Como resultado, se eliminará la línea configurada actualmente en el cursor.

Cerrando el cursor

Después de cerrar, el cursor se vuelve inaccesible para los usuarios del programa. Al cerrar se retiran todas las cerraduras instaladas durante su funcionamiento. El cierre solo se puede aplicar a cursores abiertos. Cerrado pero no cursor liberado podrá reabrirse. No está permitido cerrar un cursor no abierto.

Suelta el cursor

Cerrando el cursor no necesariamente libera la memoria asociada a él. Algunas implementaciones deben desasignarlo explícitamente mediante la declaración DEALLOCATE. Después suelta el cursor También se libera memoria, lo que permite reutilizar el nombre del cursor.

Para controlar si se ha llegado al final del cursor, se recomienda utilizar la función: @@FETCH_STATUS

La función @@FETCH_STATUS devuelve:

0 si la recuperación fue exitosa;

1 si la recuperación falló debido a un intento de recuperar una línea fuera del cursor;

2 si la recuperación falló debido a un intento de acceder a una fila eliminada o modificada.

DECLARAR @id_kl INT, @firm VARCHAR(50), @fam VARCHAR(50), @message VARCHAR(80), @nam VARCHAR(50), @d DATETIME, @p INT, @s INT SET @s=0 IMPRIMIR "Lista de compras" DECLARAR klient_cursor CURSOR LOCAL PARA SELECCIONAR Código de cliente, Empresa, Apellido DESDE Cliente DONDE Ciudad="Moscú" ORDENAR POR Empresa, Apellido ABRIR klient_cursor BUSCAR SIGUIENTE DE klient_cursor EN @id_kl, @firm, @fam MIENTRAS @@FETCH_STATUS =0 COMENZAR SELECCIONAR @message="Cliente "+@fam+ "Empresa "+ @firm IMPRIMIR @message SELECCIONAR @message="Nombre del producto Fecha de compra Costo" IMPRIMIR @message DECLARAR tovar_cursor CURSOR PARA SELECCIONAR Producto.Nombre, Transacción.Fecha, Producto .Precio* Transacción.Cantidad COMO Costo DEL Producto INNER JOIN Transacción EN Producto. Código de producto = Transacción. Código de producto DONDE Transacción. Código de cliente = @id_kl ABRIR tovar_cursor FETCH NEXT FROM tovar_cursor INTO @nam, @d, @p IF @@FETCH_STATUS<>0 PRINT "Sin compras" WHILE @@FETCH_STATUS=0 BEGIN SELECT @message=" "+@nam+" "+ CAST(@d AS CHAR(12))+" "+ CAST(@p AS CHAR(6)) PRINT @message SET @s=@s+@p FETCH NEXT FROM tovar_cursor INTO @nam, @d, @p END CLOSE tovar_cursor DEALLOCATE tovar_cursor SELECT @message="Costo total "+ CAST(@s AS CHAR(6)) PRINT @message -- pasar al siguiente cliente-- FETCH NEXT FROM klient_cursor INTO @id_kl, @firm, @fam END CLOSE klient_cursor DEALLOCATE klient_cursor Ejemplo 13.6. Cursor para mostrar una lista de productos comprados por clientes en Moscú y su costo total.

Ejemplo 13.7. Desarrollar un cursor desplazable para clientes de Moscú. Si el número de teléfono comienza con 1, elimine el cliente con ese número y en la primera entrada del cursor reemplace el primer dígito del número de teléfono con 4.

DECLARAR @firm VARCHAR(50), @fam VARCHAR(50), @tel VARCHAR(8), @message VARCHAR(80) IMPRIMIR "Lista de clientes" DECLARAR klient_cursor CURSOR GLOBAL SCROLL KEYSET PARA SELECCIONAR Empresa, Apellido, Teléfono DEL Cliente DONDE Ciudad ="Moscú" ORDENAR POR Empresa, Apellido PARA ACTUALIZAR ABRIR klient_cursor BUSCAR SIGUIENTE DE klient_cursor EN @firm, @fam, @tel MIENTRAS @@FETCH_STATUS=0 COMENZAR SELECCIONAR @message="Cliente "+@fam+ " Empresa "+ @firm " Teléfono "+ @tel IMPRIMIR @mensaje - si el número de teléfono comienza con 1, - eliminar el cliente con ese número SI a @tel LE GUSTA '1%' ELIMINAR Cliente DONDE ACTUAL DE klient_cursor MÁS - pasar al siguiente cliente FETCH NEXT FROM klient_cursor INTO @firm, @fam, @tel END FETCH ABSOLUTE 1 FROM klient_cursor INTO @firm, @fam, @tel -- en la primera entrada, reemplace el primer dígito del número de teléfono con 4 ACTUALIZAR Cliente SET Phone ='4' + DERECHA(@ tel,LEN(@tel)-1)) DONDE ACTUAL DE klient_cursor SELECT @message="Cliente "+@fam+" Empresa "+ @firm "Teléfono "+ @tel IMPRIMIR @message CERRAR klient_cursor DEASIGNAR klient_cursor Ejemplo 13.7. Cursor desplazable para clientes de Moscú.

Ejemplo 13.8. Uso cursor como parámetro de salida del procedimiento. El procedimiento devuelve un conjunto de datos: una lista de productos.

La llamada al procedimiento y la impresión de datos desde el cursor de salida se realiza de la siguiente manera:

DECLARAR @my_cur CURSOR DECLARAR @n VARCHAR(20) EXEC my_proc @cur=@my_cur SALIDA FETCH SIGUIENTE DESDE @my_cur INTO @n SELECCIONAR @n MIENTRAS (@@FETCH_STATUS=0) COMENZAR FETCH SIGUIENTE DESDE @my_cur INTO @n SELECCIONAR @n FIN CERRAR @my_cur DEASIGNAR @my_cur




Arriba