Come e quando utilizzare sys_refcursor in Oracle


Risposte:


10

Un cursore è un puntatore a un set di risultati per una query. Restituendo a sys_refcursorsi consente al client di recuperare dalla query quante o poche righe siano necessarie. Nelle applicazioni con stato questo potrebbe essere usato per sfogliare i risultati.

Un cursore può consentire una maggiore flessibilità rispetto alla scrittura di una funzione PL / SQL che restituisce un array poiché dipende completamente dal client quante righe recuperare e quando arrestare. Detto questo, non ho trovato molti casi in cui questa ulteriore flessibilità è utile.

Vale la pena notare che sys_refcursorè tipizzato debolmente, quindi puoi restituire i puntatori a query che non solo hanno clausole diverse da o dove, ma anche numeri e tipi di colonne diversi. In alternativa è possibile utilizzare il cursore fortemente tipizzato in cui sono fissate le colonne nel set di risultati.

Ciò consente di scrivere funzioni che restituiscono query diverse, in questo modo:

create function get_data ( type varchar2 ) return sys_refcursor as
  ret_cur sys_refcursor;
begin

  if type = 'EMP' then
    open ret_cur for select * from emp;
  elsif type = 'DEPT' then
    open ret_cur for select * from dept;
  end if;

  return ret_cur;
end;

Tuttavia, se stai usando sys_refcursorper creare una generica funzione "apri una query" come quella sopra probabilmente stai facendo qualcosa di sbagliato!


@Chris ... perché la tua funzione di esempio è "sbagliata?"
Johnny Wu,

2
@JohnnyWu sarà più difficile gestire una funzione "prendimi tutto". Come si esegue il test per assicurarsi di avere i risultati giusti in tutti i casi? E la sicurezza? Questo potrebbe essere necessario se stai costruendo un framework. Ma per la logica aziendale generale, è meglio avere separati get_empse get_deptsfunzioni
Chris Saxon,

1

Come esempio delle possibilità: poiché è pl / sql sul retro, è possibile definire un oggetto per rappresentare una riga, definire una tabella pl / sql di quegli oggetti,

create type T_MY_TABLE as table of t_my_object;

e termina con

OPEN p_recordset FOR select * from table( v_my_table );

Quindi, anziché costruire query dirette mongo, spesso dense e / o criptiche su una tabella di database, si può creare una tabella interna e avere tutta la potenza di pl / sql per popolarla. E il client che raccoglie il set di risultati non è il più saggio. E cambiare la definizione della tabella interna è più facile da un punto di vista gestionale che cambiare una tabella di database.

Inoltre, quando si utilizzano generatori di report come Jasper, è possibile inviare l'SQL dal report e nel database e chiamare semplicemente la procedura per ottenere il recordset, lasciando il lato del report a concentrarsi sulla formattazione.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.