In SQL i cursori fungono da puntatore che consente al linguaggio di programmazione dell'applicazione di gestire i risultati delle query una riga alla volta. Questo articolo esplora rapidamente il concetto alla base e mostra come dichiarare i cursori, aprirli, recuperarne i dati e quindi chiuderli.
Cursori SQL
I dati nel database relazionale sono gestiti sotto forma di insiemi. Di conseguenza, i risultati delle query restituiti dalle istruzioni SQL SELECT vengono definiti set di risultati. I set di risultati non sono altro che combinazioni di una o più righe e colonne estratte da una o più tabelle. Puoi scorrere i set di risultati per estrarre le informazioni di cui hai bisogno. Gli elementi di dati restituiti vengono utilizzati da linguaggi di programmazione come Java o qualsiasi altro per scopi applicativi specifici. Ma qui sta il problema del disadattamento di impedenza a causa della differenza di costrutto tra modello di database e modello di linguaggio di programmazione.
Un modello di database SQL ha tre costrutti principali:
- colonne (o attributi) e relativi tipi di dati
- righe (record o tuple)
- tabelle (raccolta di record)
Pertanto, la mancata corrispondenza principale tra due modelli è:
- I tipi di dati degli attributi disponibili nel modello di database non sono gli stessi dei tipi di variabili utilizzati nei linguaggi di programmazione. Esistono molte lingue host e ognuna ha un tipo di dati diverso. Ad esempio, i tipi di dati di C/C++ e Java sono diversi, così come i tipi di dati SQL. Quindi è necessario un meccanismo vincolante per mitigare il problema dell'incompatibilità.
- Il risultato restituito dalle istruzioni SQL SELECT sono set multipli di record in cui ogni record è una raccolta di attributi. I linguaggi di programmazione host in genere funzionano su singoli valori di dati della tupla restituiti dalla query. Pertanto, è essenziale che il risultato della query SQL corrisponda alla struttura dei dati supportata dal linguaggio di programmazione. Il meccanismo di loop sulle tuple è necessario per scorrere le tuple ei loro valori di attributo.
Il cursore agisce come una variabile iteratore per scorrere le tuple restituite dalla query SQL ed estrarre i singoli valori all'interno di ciascuna tupla che possono quindi essere mappati al tipo appropriato di variabili di programma.
Il cursore, quindi, funge da puntatore che consente al linguaggio di programmazione di elaborare il risultato della query un record alla volta. Un cursore può attraversare tutte le righe del risultato di una query concentrandosi su una riga alla volta. Considera la seguente query SQL:
SELECT emp_no, first_name, last_name, birth_date FROM employees WHERE MONTH(birth_date) = MONTH(CURRENT_DATE) AND DAY(birth_date) = DAY(CURRENT_DATE);
Il risultato della query dalla dichiarazione di cui sopra restituisce i dettagli dei dipendenti di tutti quei dipendenti la cui data di nascita cade nel giorno corrente di un determinato mese. Il risultato può contenere molte righe, ma la lingua dell'applicazione host può gestire una riga alla volta. Di conseguenza, il cursore viene dichiarato come un'istruzione SQL incorporata all'interno del linguaggio di programmazione dell'applicazione. Il cursore viene quindi aperto in modo molto simile a un file ed estrae una singola riga dal risultato della query. Successivamente vengono estratte le altre righe, in sequenza fino alla chiusura del cursore.
Dichiarazione di un cursore
I cursori sono dichiarati in modo molto simile a una variabile. Viene assegnato un nome, ci sono istruzioni per aprire il cursore, recuperare il risultato della query e infine chiudere il cursore. Si noti che diverse implementazioni SQL supportano l'uso dei cursori in un modo diverso. Ma c'è un accordo generale su come dovrebbe essere scritto il cursore.
Dobbiamo utilizzare le istruzioni SQL per implementare completamente la funzionalità del cursore perché la semplice dichiarazione di un cursore non è sufficiente per estrarre i dati da un database SQL. Ci sono quattro passaggi fondamentali per dichiarare un cursore:
DICHIARA CURSORE: La dichiarazione inizia assegnando un nome al cursore e assegnando l'espressione della query da richiamare all'apertura del cursore.
APERTO: L'istruzione open esegue l'espressione della query assegnata e prepara il risultato della query per il successivo FETCH.
RICERCA: Recupera i valori dei dati in variabili che possono quindi essere passate al linguaggio di programmazione host o ad altre istruzioni SQL incorporate.
CHIUDI: Il cursore è chiuso dal recupero di altri risultati della query.
La sintassi è la seguente:
DECLARE <cursor_name> [SENSITIVE | INSENSITIVE | ASENSITIVE] [SCROLL | NO SCROLL] CURSOR [ WITH HOLD | WITHOUT HOLD] [ WITH RETURN | WITHOUT RETURN] FOR <sql_query_expression> [ ORDER BY <sort_expression>] [ FOR {READ ONLY | UPDATE [ OF <list_of_column>]}]
La parte essenziale di una dichiarazione del cursore è la seguente:
DECLARE <cursor_name> FOR <sql_query_expression>
La parte facoltativa come [SENSITIVE | INSENSIVO | ASENSITIVE] indica se il cursore è sensibile alle modifiche e se rifletterle nel risultato della query. SENSIBILE significa che il cursore è interessato dalle modifiche, INSENSITIVO significa che il cursore non è interessato e ASENSITIVO significa che le modifiche possono essere o meno visibili al cursore. Se non specificato assume l'opzione ASENSITIVE.
L'opzione [SCORRIMENTO | NOSCROLL] definisce la capacità di scorrimento del cursore. Se non specificato, presuppone l'opzione NO SCROLL.
L'opzionale [ CON TENUTA | WITHOUT HOLD] definisce se sospendere o chiudere automaticamente quando viene eseguita la transazione dovuta al cursore. Se non specificato mantiene l'opzione SENZA ATTESA.
L'opzionale [ CON RESO | WITHOUT RETURN] determina se restituire il set di risultati del cursore all'invocatore, ad esempio un'altra routine SQL o un linguaggio host. Se non specificato significa SENZA RESO.
La clausola ORDER BY viene utilizzata per ordinare il risultato della query restituito in base alla tecnica di ordinamento specificata.
L'opzione UPDATE fa riferimento all'uso dell'istruzione UPDATE o DELETE è l'associazione con le righe restituite dall'istruzione SELECT del cursore. Qualsiasi modifica di questo tipo non è possibile se specifichiamo l'opzione SOLA LETTURA. Se non specificato, per impostazione predefinita viene utilizzata l'opzione UPDATE.
Pertanto, un semplice cursore può essere dichiarato come segue:
DECLARE mycursor CURSOR FOR SELECT emp_no, first_name, last_name, birth_date FROM employees WHERE MONTH(birth_date) = MONTH(CURRENT_DATE) AND DAY(birth_date) = DAY(CURRENT_DATE);
Cursori in MySQL
Tipicamente, ci sono due tipi di cursori trovati in MySQL:cursori di sola lettura e di sola andata. Questi cursori possono essere utilizzati per la stored procedure MySQL. Questi cursori ci aiutano a scorrere i risultati della query una riga alla volta e a recuperare le variabili per un'ulteriore elaborazione. È possibile dichiarare più di un cursore e nidificarli in loop. Si noti che i cursori sono di sola lettura perché vengono utilizzati per scorrere le tabelle temporanee. Il cursore in genere esegue la query mentre la apriamo.
Uno dei problemi con il cursore in MySQL è che potrebbero rallentare le prestazioni della query a causa di operazioni di I/O aggiuntive che eseguono. Ciò vale in particolare per i tipi di dati di grandi dimensioni come BLOB e TEXT. Poiché i cursori funzionano con le tabelle temporanee, questi tipi non sono supportati nelle tabelle in memoria. Pertanto, mentre si lavora con questi tipi, MySQL deve creare tabelle temporanee su disco e ciò richiede molte operazioni di I/O e anche in dispositivi lenti come i dischi. Questo è il motivo principale del rallentamento delle prestazioni del cursore.
MySQL inoltre non supporta i cursori lato client, tuttavia l'API client può emularli se necessario. Ma questo non è molto diverso dal recuperare il risultato in un array in un linguaggio di programmazione come Java e manipolarlo lì.
Ecco un esempio su come scrivere i cursori in MySQL.
CREATE PROCEDURE 'cursor_demo'() BEGIN DECLARE done INT DEFAULT FALSE; DECLARE id INT(11); DECLARE fn varchar(14); DECLARE ln varchar(16); DECLARE bdate date; DECLARE mycursor CURSOR FOR SELECT emp_no, first_name, last_name, birth_date FROM employees WHERE MONTH(birth_date)=MONTH(CURRENT_DATE) AND DAY(birth_date)=DAY(CURRENT_DATE); DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE; OPEN mycursor; fetch_loop: LOOP FETCH mycursor INTO id, fn, ln, bdate; IF done THEN LEAVE fetch_loop; END IF; SELECT id, fn, ln, bdate; END LOOP; CLOSE mycursor; END
Chiamare la procedura memorizzata come segue:
mysql> CALL cursor_demo
La procedura recupera le righe da una tabella denominata employee la cui data di nascita corrisponde al giorno e al mese correnti in un cursore denominato miocursore e li stampa semplicemente usando l'istruzione SELECT.
Fare riferimento alla documentazione MySQL sul cursore per ulteriori informazioni.
Conclusione
I cursori non sono altro che puntatori ai set di record restituiti dalla query SQL. Il puntatore in genere punta a una riga alla volta e può essere attraversato in un ciclo per recuperare singoli record. SQL viene normalmente utilizzato per la chiamata diretta per accedere e creare oggetti dati. I cursori forniscono la tecnica dell'SQL interattivo in cui abilita l'esecuzione ad hoc di istruzioni SQL facilitata tramite l'applicazione client. Il meccanismo del cursore sfrutta il modello di accesso ai dati in cui le istruzioni SQL sono incorporate nel linguaggio host come C, C++ o Java ecc. Questo è solo un assaggio di ciò con cui il cursore sta per iniziare. Fare riferimento alla documentazione del database SQL appropriato per i dettagli sulle norme specifiche di varie implementazioni.
# # #