2010-03-23 3 views
4

SQL Server est capable de retourner les résultats de plusieurs requêtes en un seul aller-retour,: par exemplemultiples d'Oracle resultsets dans Odp.net, sans refcursors

select a, b, c from y; 
select d, e, f from z; 

Oracle n'aime pas cette syntaxe. Il est possible d'utiliser des curseurs de référence, comme ceci:

begin 
    open :1 for select count(*) from a; 
    open :2 for select count(*) from b; 
end; 

Cependant, vous encourez une pénalité dans les curseurs d'ouverture/fermeture et vous pouvez maintenir les verrous de base de données pendant une période prolongée. Ce que je voudrais faire est de récupérer les résultats de ces deux requêtes en une seule fois, en utilisant Odp.net. C'est possible?

+1

Un select, dans Oracle, ne prend pas de verrous. Et les curseurs sont utilisés implicitement de toute façon, donc je ne pense pas que vous épargniez beaucoup, sauf sur les allers-retours du réseau. –

+0

@Gary Les allers-retours au réseau sont coûteux. Si vous exécutez plusieurs requêtes dans une seule commande dans SQL Server, vous bénéficiez d'une augmentation appréciable de la performance, en particulier si vous effectuez beaucoup de tâches en même temps. Je ne vois pas pourquoi cela ne devrait pas être possible dans Oracle. Comment Oracle prend-il en charge les lectures répétables sans verrous? –

+1

Oracle utilise le contrôle de concurrence multi-versionnage. Fondamentalement, il conserve un historique des modifications effectuées (au moins aussi longtemps que la transaction active la plus ancienne), et s'il rencontre des données qui ont changé, il regarde l'historique pour voir quel était l'état des données lorsque la requête a démarré. SQL Server 2005 a ajouté ceci et l'a appelé isolation de capture instantanée. –

Répondre

6

Dans Oracle, le curseur de référence est un pointeur sur des données plutôt que sur des données. Ainsi, si une procédure renvoie deux curseurs de référence, le client doit toujours aller chercher les lignes de ces curseurs (et encourir les hits réseau). En tant que tel, si les volumes de données sont petits, vous souhaitez probablement appeler une procédure qui retourne simplement les valeurs. Si les volumes de données sont volumineux (des milliers de lignes), il ne s'agira pas d'un seul et même trajet réseau. Par conséquent, un ou deux de plus lorsque vous basculez entre les curseurs ne fera pas beaucoup de différence.

Un autre choix consiste à avoir un seul select de retour toutes les lignes. Cela pourrait être un simple UNION ALL

select a, b, c from y union all select d, e, f from z; 

Il pourrait être une fonction de table pipe-line

create or replace package test_pkg is 
    type rec_two_cols is record 
     (col_a varchar2(100), 
     col_b  varchar2(100)); 
    type tab_two_cols is table of rec_two_cols; 
    function ret_two_cols return tab_two_cols pipelined; 
end; 
/

create or replace package body test_pkg is 
    function ret_two_cols return tab_two_cols pipelined 
    is 
     cursor c_1 is select 'type 1' col_a, object_name col_b from user_objects; 
     cursor c_2 is select 'type 2' col_a, object_name col_b from user_objects; 
     r_two_cols rec_two_cols; 
    begin 
     for c_rec in c_1 loop 
      r_two_cols.col_a := c_rec.col_a; 
      r_two_cols.col_b := c_rec.col_b; 
      pipe row (r_two_cols); 
     end loop; 
     for c_rec in c_2 loop 
      r_two_cols.col_a := c_rec.col_a; 
      r_two_cols.col_b := c_rec.col_b; 
      pipe row (r_two_cols); 
     end loop; 
     return; 
    end; 
end; 
/
select * from table(test_pkg.ret_two_cols); 

Je crois que les versions les plus récentes de ODP pour 11g permettent des types définis par l'utilisateur qui peut aider.

Questions connexes