# Cursore (basi di dati)

In informatica, un cursore dei database è una struttura che permette di scorrere i record restituiti da una query. Essi possono essere di sola lettura o, se l'implementazione lo consente, possono essere usati per modificare o cancellare le righe. I cursori sono più veloci se sono in grado di muoversi soltanto in avanti, ma se l'implementazione lo consente è possibile creare cursori in grado di spostarsi in entrambe le direzioni. Possono essere usati all'interno di una stored procedure, o di un programma esterno, per elaborare l'insieme dei risultati una riga per volta. In particolare, solo grazie ai cursori le stored procedure possono implementare una business logic complessa che legge più tuple da una tabella e le esamina una per una.

## Operazioni legate ai cursori
### Dichiarazione

Prima di poter utilizzare un cursore in qualsiasi modo, è necessario dichiararlo. La sintassi standard SQL per dichiarare un cursore è la seguente:
La query non può essere una stringa, di conseguenza gli standard non prevedono la possibilità di abbinare i cursori a comandi SQL dinamici.
Per dichiarare un cursore in grado di spostarsi indietro, è necessario specificare l'opzione SCROLL:

### Apertura

Dopo aver dichiarato un cursore, è possibile aprirlo:
È a questo punto che, di solito, le implementazioni di SQL eseguono la query associata al cursore. Ogni operazione di lettura e di modifica può essere eseguita solo dopo l'apertura (e prima della chiusura) del cursore.

### Lettura

È possibile spostare il cursore alla riga successiva (o alla prima riga, se nessuna riga è stata letta) tramite il seguente comando:
Le variabili devono essere tante quante i valori estratti dalla SELECT per ogni riga. I nomi delle variabili devono essere separate da virgole e, opzionalmente, da spaziature di qualsiasi tipo.
Se il tipo di cursore e il DBMS lo permettono, è anche possibile spostarsi indietro, alla prima riga, all'ultima o in una posizione arbitraria.
Per spostarsi alla riga successiva è possibile specificare esplicitamente l'opzione NEXT, che comunque è il default. Per spostarsi alla riga precedente si usa PRIOR, per la prima FIRST e per l'ultima LAST. Esempi:
È anche possibile specificare un valore numerico, che rappresenta il numero progressivo della riga che si desidera selezionare. Questo valore può essere assoluto o relativo. Se è relativo, un numero positivo indica uno spostamento in avanti, mentre un numero negativo indica uno spostamento indietro:

### Modifica

Lo standard SQL:2003 prevede la possibilità di eseguire un'istruzione DELETE o UPDATE sulla riga selezionata da un dato cursore. Per fare questo si utilizza la clausola CURRENT OF all'interno della clausola WHERE:

### Chiusura

Per liberare la memoria occupata dai risultati della query e dal cursore stesso è necessario chiudere il cursore:

### Alternative ai cursori

Vi sono casi in cui i cursori sono lungi dall'essere la soluzione più efficiente e programmatori che non amano utilizzarli. Spesso esistono delle alternative all'uso dei cursori.

#### SELECT ... INTO lista_variabili

Alcuni DBMS permettono di utilizzare la sintassi SELECT ... INTO per inserire alcuni valori in altrettante variabili. Questo è certamente il modo più efficiente di leggere uno o più valori da una sola tupla. In questi casi, è buona pratica evitare di utilizzare un cursore.

#### JOIN

Le JOIN SQL possono essere piuttosto complicate da scrivere, soprattutto se non si conosce bene la teoria relazionale. A volte i cursori vengono utilizzati proprio per evitare di scrivere JOIN complesse: si esegue un ciclo su una tabella utilizzando un cursore, e per ogni record si compone dinamicamente una query che leggerà un'altra tabella. Tuttavia una JOIN è sempre più efficiente di un cursore.

#### HANDLER

MySQL e MariaDB supportano il comando HANDLER, che permette di scorrere le righe di una tabella in modo simile ai cursori. Non si basa però su una query. È possibile specificare una condizione, mentre è necessario che i record vengano ordinati in base a un indice. HANDLER può essere visto come un cursore di sola lettura piuttosto limitato.