Informazioni sui tipi di cursore

Nei database relazionali le operazioni vengono eseguite su set di righe completi. Il set di righe restituito da un'istruzione SELECT include tutte le righe che soddisfano le condizioni specificate nella clausola WHERE dell'istruzione. Il set di righe completo restituito dall'istruzione è definito set di risultati. Le applicazioni non sono sempre in grado di gestire in modo efficiente un intero set di risultati come singola unità. In tali applicazioni deve essere pertanto disponibile un meccanismo per l'elaborazione di una singola riga o di un blocco di righe di dimensioni ridotte. I cursori sono un'estensione dei set di risultati che offrono tale meccanismo.

I cursori estendono le funzionalità di elaborazione dei set di risultati nei modi seguenti:

  • Consentono il posizionamento in corrispondenza di righe specifiche del set di risultati.

  • Consentono di recuperare una riga o un blocco di righe dalla posizione corrente nel set di risultati.

  • Supportano le modifiche ai dati della riga in corrispondenza della posizione corrente nel set di risultati.

  • Supportano livelli diversi di visibilità per le modifiche apportate da altri utenti ai dati del database inclusi nel set di risultati.

Nota

Per una descrizione completa dei tipi di cursore di SQL Server, vedere l'argomento "Tipi di cursore (Motore di database)" nella documentazione in linea di SQL Server.

La specifica JDBC fornisce supporto per cursori forward-only e scorrevoli sensibili o non sensibili alle modifiche apportate da altri processi e che possono essere di sola lettura o aggiornabili. Questa funzionalità viene fornita dalla classe SQLServerResultSet del driver JDBC per Microsoft SQL Server 2005.

Il driver JDBC supporta i tipi di cursore seguenti:

Tipo di set di risultati (cursore) Tipo di cursore di SQL Server Caratteristiche Proprietà selectMethod Proprietà responseBuffering Descrizione

TYPE_FORWARD_ONLY (CONCUR_READ_ONLY)

N/D

Forward-only, di sola lettura

direct

full

L'applicazione deve eseguire una singola iterazione (in avanti) nel set di risultati. Si tratta del comportamento predefinito, corrispondente a un cursore TYPE_SS_DIRECT_FORWARD_ONLY. Tramite il driver viene letto l'intero set di risultati dal server caricandolo in memoria durante l'esecuzione dell'istruzione.

TYPE_FORWARD_ONLY (CONCUR_READ_ONLY)

N/D

Forward-only, di sola lettura

direct

adaptive

L'applicazione deve eseguire una singola iterazione (in avanti) nel set di risultati. Il comportamento corrisponde a quello di un cursore TYPE_SS_DIRECT_FORWARD_ONLY. Tramite il driver le righe vengono lette dal server quando vengono richieste dall'applicazione, riducendo così al minimo l'utilizzo della memoria sul lato client.

TYPE_FORWARD_ONLY (CONCUR_READ_ONLY)

Fast forward

Forward-only, di sola lettura

cursor

full o adaptive

L'applicazione deve eseguire una singola iterazione (in avanti) nel set di risultati utilizzando un cursore server. Il comportamento corrisponde a quello di un cursore TYPE_SS_SERVER_CURSOR_FORWARD_ONLY.

TYPE_FORWARD_ONLY (CONCUR_UPDATABLE)

Dinamico (forward-only)

Forward-only, aggiornabile

direct o cursor

full o adaptive

L'applicazione deve eseguire una singola iterazione (in avanti) nel set di risultati per aggiornare una o più righe.

Per impostazione predefinita, la dimensione di recupero viene fissata quando l'applicazione chiama il metodo setFetchSize dell'oggetto SQLServerResultSet.

Per ottenere il buffer adattivo per questo caso, l'applicazione deve chiamare il metodo setResponseBuffering dell'oggetto SQLServerStatement fornendo un valore String "adaptive".

TYPE_SCROLL_INSENSITIVE

Statico

Scorrevole, non aggiornabile

direct o cursor

full o adaptive

L'applicazione richiede uno snapshot del database.

TYPE_SCROLL_SENSITIVE

Keyset

Scorrevole e aggiornabile. Gli aggiornamenti delle righe sono visibili e le eliminazioni vengono visualizzate come dati mancanti. Gli inserimenti dall'interno del set di risultati sono visibili, mentre quelli dall'esterno del set di risultati no.

direct o cursor

full o adaptive

Nell'applicazione devono essere visualizzati i dati modificati solo per le righe esistenti.

TYPE_SS_DIRECT_FORWARD_ONLY

N/D

Forward-only, di sola lettura

direct o cursor

full o adaptive

Valore intero = 2003. Fornisce un cursore sul lato client di sola lettura completamente memorizzato nel buffer. Non viene creato alcun cursore server.

TYPE_SS_SERVER_CURSOR_FORWARD_ONLY

Fast forward

Forward-only

direct o cursor

full o adaptive

Valore intero = 2004. Veloce, con accesso a tutti i dati.

TYPE_SS_SCROLL_STATIC

Statico

Gli aggiornamenti di altri utenti non vengono riflessi

direct o cursor

full o adaptive

Valore intero = 1004. L'applicazione richiede uno snapshot del database. Si tratta del sinonimo specifico di SQL Server per il tipo JDBC TYPE_SCROLL_INSENSITIVE.

TYPE_SS_SCROLL_KEYSET

Keyset

Gli aggiornamenti di altri utenti vengono riflessi. L'appartenenza alle righe è fissa.

direct o cursor

full o adaptive

Valore intero = 1005. Nell'applicazione devono essere visualizzati i dati modificati solo per le righe esistenti. Si tratta del sinonimo specifico di SQL Server per il tipo JDBC TYPE_SCROLL_SENSITIVE.

TYPE_SS_SCROLL_DYNAMIC

Dinamico

Scorrevole e aggiornabile. Gli aggiornamenti delle righe sono visibili e le eliminazioni vengono visualizzate come dati mancanti temporanei nel buffer di recupero corrente. Gli inserimenti dall'interno e dall'esterno del set di risultati sono visibili.

direct o cursor

full o adaptive

Valore intero = 1006. Nell'applicazione devono essere visualizzati i dati modificati per le righe esistenti, nonché le righe inserite ed eliminate nel corso della durata del cursore.

Posizionamento dei cursori

I cursori TYPE_FORWARD_ONLY, TYPE_SS_DIRECT_FORWARD_ONLY e TYPE_SS_SERVER_CURSOR_FORWARD_ONLY supportano solo il metodo di posizionamento next.

Il cursore TYPE_SS_SCROLL_DYNAMIC non supporta i metodi absolute e getRow. È possibile ottenere un risultato simile a quello del metodo absolute tramite una combinazione di chiamate ai metodi first e relative per i cursori dinamici.

Il metodo getRow è supportato solo dai cursori TYPE_FORWARD_ONLY, TYPE_SS_DIRECT_FORWARD_ONLY, TYPE_SS_SERVER_CURSOR_FORWARD_ONLY, TYPE_SS_SCROLL_KEYSET e TYPE_SS_SCROLL_STATIC. Il metodo getRow con tutti i tipi di cursore forward-only restituisce il numero di righe lette fino a quel momento tramite il cursore.

Nota

Quando un'applicazione esegue una chiamata non supportata ai metodi di posizionamento del cursore o al metodo getRow, viene generata un'eccezione con il messaggio "L'operazione richiesta non è supportata con questo tipo di cursore".

Solo il cursore TYPE_SS_SCROLL_KEYSET e l'equivalente TYPE_SCROLL_SENSITIVE espongono le righe eliminate. Se il cursore viene posizionato in una riga eliminata, i valori della colonna non sono disponibili e il metodo rowDeleted restituisce "true". Le chiamate ai metodi get<Type> generano un'eccezione con il messaggio "Impossibile ottenere un valore da una riga eliminata". Le righe eliminate non possono essere aggiornate. Se si tenta di chiamare un metodo update<Type> in una riga eliminata, viene generata un'eccezione con il messaggio "Non è possibile aggiornare una riga eliminata". Il cursore TYPE_SS_SCROLL_DYNAMIC ha lo stesso comportamento fino a quando non viene tolto dal buffer di recupero corrente.

I cursori forward e dinamici espongono le righe eliminate in modo simile, ma solo fino a quando rimangono accessibili nel buffer di recupero. Per i cursori forward, questo comportamento è piuttosto lineare. Per i cursori dinamici, si tratta di un comportamento più complesso quando la dimensione di recupero è maggiore di 1. Un'applicazione può spostare il cursore avanti e indietro nella finestra definita dal buffer di recupero, ma la riga eliminata non viene più visualizzata all'uscita dal buffer di recupero originale in cui è stata aggiornata. Se non si desidera che in un'applicazione vengano visualizzate righe eliminate temporanee tramite i cursori dinamici, è necessario utilizzare un'istruzione FETCH RELATIVE con l'argomento 0.

Se i valori chiave della riga di un cursore TYPE_SS_SCROLL_KEYSET o TYPE_SCROLL_SENSITIVE vengono aggiornati con il cursore, la riga mantiene la propria posizione originale nel set di risultati, indipendentemente dal fatto che la riga aggiornata soddisfi i criteri di selezione del cursore. Se la riga è stata aggiornata all'esterno del cursore, nella posizione originale della riga verrà visualizzata una riga eliminata, ma la riga verrà visualizzata nel cursore solo se un'altra riga con i nuovi valori chiave era presente nel cursore ma è stata quindi eliminata.

Per i cursori dinamici, le righe aggiornate mantengono la posizione all'interno del buffer di recupero fino a quando la finestra definita dal buffer di recupero non viene chiusa. Successivamente, le righe aggiornate possono venire visualizzate in posizioni diverse nel set di risultati o scomparire completamente. Per le applicazioni in cui è necessario evitare le inconsistenze temporanee nel set di risultati, è necessario utilizzare una dimensione di recupero pari a 1. L'impostazione predefinita è 8 righe con concorrenza CONCUR_SS_SCROLL_LOCKS e 128 righe con altre concorrenze.

Conversione dei cursori

A volte, in SQL Server può venire implementato un tipo di cursore diverso da quello richiesto e questo comportamento è noto come conversione implicita del cursore o degradazione del cursore. Per ulteriori informazioni sulla conversione implicita del cursore, vedere l'argomento "Utilizzo della conversione implicita del cursore" nella documentazione in linea di SQL Server.

In SQL Server 2000 quando si aggiornano i dati tramite i set di risultati ResultSet.TYPE_SCROLL_SENSITIVE e ResultSet.CONCUR_UPDATABLE viene generata un'eccezione con il messaggio "Il cursore è READ ONLY". Questa eccezione si verifica perché in SQL Server 2000 è stata eseguita una conversione implicita del cursore per tale set di risultati e non è stato restituito il cursore aggiornabile richiesto.

Per ovviare a questo problema, è possibile scegliere una delle due soluzioni seguenti:

  • Verificare che la tabella sottostante disponga di una chiave primaria.

  • Utilizzare SQLServerResultSet.TYPE_SS_SCROLL_DYNAMIC anziché ResultSet.TYPE_SCROLL_SENSITIVE durante la creazione di un'istruzione.

Aggiornamento dei cursori

Gli aggiornamenti sul posto sono supportati per i cursori se la concorrenza e il tipo di cursore supportano gli aggiornamenti. Se il cursore non è posizionato in una riga aggiornabile nel set di risultati (nessuna chiamata al metodo get<Type> ha avuto esito positivo), una chiamata a un metodo update<Type> genera un'eccezione con il messaggio "Il set di risultati non ha una riga corrente". In base alla specifica JDBC viene generata un'eccezione quando viene chiamato un metodo di aggiornamento per una colonna di un cursore di tipo CONCUR_READ_ONLY. Nei casi in cui la riga non è aggiornabile, ad esempio a causa di un conflitto di concorrenza ottimistica come un aggiornamento o un'eliminazione in conflitto, l'eccezione potrebbe non venire generata fino a quando non viene chiamato il metodo insertRow, updateRow o deleteRow.

Dopo una chiamata a update<Type>, non è possibile accedere alla colonna interessata tramite get<Type> fino a quando non viene chiamato il metodo updateRow o cancelRowUpdates. In questo modo è possibile evitare i problemi che possono verificarsi quando una colonna viene aggiornata utilizzando un tipo diverso da quello restituito dal server e le chiamate al metodo Get successive possono richiamare conversioni del tipo sul lato client che forniscono risultati non accurati. Le chiamate a get<Type> generano un'eccezione con il messaggio "Impossibile accedere alle colonne aggiornate fino a quando non è stato chiamato updateRow() o cancelRowUpdates()".

Nota

Se il metodo updateRow viene chiamato quando non è stata aggiornata alcuna colonna, il driver JDBC genera un'eccezione con un messaggio che indica che è stato chiamato il metodo updateRow () senza che siano state aggiornate le colonne.

Dopo la chiamata a moveToInsertRow, viene generata un'eccezione se nel set di risultati viene chiamato qualsiasi metodo ad eccezione di get<Type>, update<Type>, insertRow, e dei metodi di posizionamento del cursore, incluso moveToCurrentRow. Il metodo moveToInsertRow consente di attivare in modo efficace la modalità di inserimento per il set di risultati e i metodi di posizionamento del cursore consentono di interrompere tale modalità. Le chiamate ai metodi di posizionamento relativo del cursore consentono di spostare il cursore rispetto alla posizione in cui si trovava prima della chiamata al metodo moveToInsertRow. Dopo le chiamate ai metodi di posizionamento del cursore, l'eventuale posizione di destinazione del cursore diventa la nuova posizione del cursore.

Se la chiamata ai metodi di posizionamento del cursore eseguita in modalità di inserimento non ha esito positivo, la posizione del cursore dopo tale chiamata corrisponde alla posizione originale del cursore prima della chiamata a moveToInsetRow. Se il metodo insertRow ha esito negativo, il cursore rimane nella riga di inserimento e in modalità di inserimento.

Inizialmente, le colonne nella riga di inserimento hanno uno stato non inizializzato. Le chiamate al metodo update<Type> consentono di impostare lo stato delle colonne come inizializzato. Una chiamata al metodo get<Type> per una colonna non inizializzata genera un'eccezione. Una chiamata al metodo insertRow ripristina lo stato non inizializzato per tutte le colonne nella riga di inserimento.

Se quando viene chiamato il metodo insertRow vi sono colonne non inizializzate, in tali colonne viene inserito il relativo valore predefinito. Se non è disponibile un valore predefinito, ma la colonna ammette valori Null, viene inserito NULL. Se non è disponibile un valore predefinito e la colonna non ammette valori Null, il server restituisce un errore e viene generata un'eccezione.

Nota

Le chiamate al metodo getRow eseguite in modalità di inserimento restituiscono 0.

Il driver JDBC non supporta eliminazioni o aggiornamenti posizionati. In base alla specifica JDBC, il metodo setCursorName non ha effetto e il metodo getCursorName quando viene chiamato genera un'eccezione.

I cursori di sola lettura e statici non sono mai aggiornabili.

In SQL Server i cursori server sono limitati a un singolo set di risultati. Se un batch o una stored procedure contiene più istruzioni, è necessario utilizzare un cursore client di sola lettura forward-only.

Memorizzazione nel buffer delle risposte dei cursori

Qualsiasi set di risultati per il quale è indicato un tipo di cursore di SQL Server nella tabella precedente può memorizzare nel buffer fino al numero di righe specificato dal metodo setFetchSize dell'oggetto SQLServerResultSet. In tali situazioni il driver JDBC per Microsoft SQL Server 2005 versione 1.2 ignora il valore dell'impostazione responseBuffering ad eccezione del caso in cui l'applicazione sostituisce l'impostazione responseBuffering, come specificato nel caso di TYPE_FORWARD_ONLY (CONCUR_UPDATABLE). In tal caso, l'applicazione può sostituire l'impostazione responseBuffering chiamando il metodo setResponseBuffering dell'oggetto SQLServerStatement con un valore String "adaptive".

Vedere anche

Altre risorse

Gestione dei set di risultati con il driver JDBC