2010-08-19 3 views
15

Dans MS SQL Server, si je souhaite vérifier les résultats d'une procédure stockée, il se peut que j'exécute ce qui suit dans Management Studio.Comment obtenez-vous des résultats bien formatés à partir d'une procédure Oracle qui renvoie un curseur de référence?

--SQL SERVER WAY 
exec sp_GetQuestions('OMG Ponies') 

La sortie dans le volet de résultats peut ressembler à ceci.

ID Title            ViewCount Votes 
----- ------------------------------------------------- ---------- -------- 
2165 Indexed View vs Indexes on Table     491   2 
5068 SQL Server equivalent to Oracle’s NULLS FIRST  524   3 
1261 Benefits Of Using SQL Ordinal Position Notation? 377   2 

(3 row(s) affected) 

Pas besoin d'écrire des boucles ou des instructions PRINT.

Pour faire la même chose dans Oracle je pourrais exécuter le bloc anonyme suivant dans SQL Developer

--ORACLE WAY 
    DECLARE 
     OUTPUT MYPACKAGE.refcur_question; 
     R_OUTPUT MYPACKAGE.r_question; 
     USER VARCHAR2(20); 

BEGIN 

    dbms_output.enable(10000000); 
    USER:= 'OMG Ponies'; 
    recordCount := 0; 



    MYPACKAGE.GETQUESTIONS(p_OUTPUT => OUTPUT, 
    p_USER=> USER, 

) ; 




    DBMS_OUTPUT.PUT_LINE('ID | Title | ViewCount | Votes'); 

    LOOP 
    FETCH OUTPUT 
    INTO R_OUTPUT; 

     DBMS_OUTPUT.PUT_LINE(R_OUTPUT.QUESTIONID || '|' || R_OUTPUT.TITLE 
       '|' || R_OUTPUT.VIEWCOUNT '|' || R_OUTPUT.VOTES); 
      recordCount := recordCount+1; 




EXIT WHEN OUTPUT % NOTFOUND; 
     END LOOP; 
     DBMS_OUTPUT.PUT_LINE('Record Count:'||recordCount); 
     CLOSE OUTPUT; 


    END; 

Ce sorties comme

ID|Title|ViewCount|Votes 
2165|Indexed View vs Indexes on Table|491|2 
5068|SQL Server equivalent to Oracle’s NULLS FIRST|524|3 
1261|Benefits Of Using SQL Ordinal Position Notation?|377|2 
Record Count: 3 

Ainsi, la version SQL a 1 ligne et l'oracle a 18 et la sortie est moche. C'est exacerbé s'il y a beaucoup de colonnes et/ou les données sont numériques.

Ce qui est étrange pour moi à ce sujet est que si j'écris cette déclaration soit dans SQL Developer ou un studio de gestion ...

SELECT 
ID, 
Title, 
ViewCount, 
Votes 
FROM votes where user = 'OMG Ponies' 

Les résultats sont assez similaires. Cela me donne l'impression de manquer une technique ou d'utiliser le mauvais outil.

Répondre

16

Si GetQuestions est une fonction renvoyant un refcursor, qui semble être ce que vous avez dans la version SQL Server, plutôt que vous pourrez peut-être faire quelque chose comme ceci:

select * from table(MyPackage.GetQuestions('OMG Ponies')); 

Ou si vous en avez besoin dans un bloc PL/SQL, vous pouvez utiliser la même sélection dans un curseur.

Vous pouvez également avoir la fonction produire les instructions dbms_output à la place afin qu'ils soient toujours disponibles pour le débogage, bien que cela ajoute un peu de frais généraux.

Modifier

Hmmm, pas sûr qu'il est possible de cast() refcursor retourné à un type utilisable, à moins que vous êtes prêt à déclarer votre propre type (et une table de ce type) à l'extérieur du paquet. Vous pouvez le faire bien, pour vider les résultats:

create package mypackage as 
    function getquestions(user in varchar2) return sys_refcursor; 
end mypackage; 
/

create package body mypackage as 
    function getquestions(user in varchar2) return sys_refcursor as 
     r sys_refcursor; 
    begin 
     open r for 
      /* Whatever your real query is */ 
      select 'Row 1' col1, 'Value 1' col2 from dual 
      union 
      select 'Row 2', 'Value 2' from dual 
      union 
      select 'Row 3', 'Value 3' from dual; 
      return r; 
    end; 
end mypackage; 
/

var r refcursor; 
exec :r := mypackage.getquestions('OMG Ponies'); 
print r; 

Et vous pouvez utiliser le résultat de l'appel dans une autre procédure ou une fonction; c'est juste d'y arriver en dehors de PL/SQL qui semble être un peu compliqué.

Edité ajouter: Avec cette approche, si elle est une procédure que vous pouvez faire essentiellement la même chose:

var r refcursor; 
exec mypackage.getquestions(:r, 'OMG Ponies'); 
print r; 
+0

La version de SQL Server n'est probablement pas une fonction. Dans SQL Server, les procédures stockées qui retournent ensemble comme résultats ont simplement des instructions 'select' qui ne sont pas liées à un curseur. Obtenir les résultats de l'exécution d'une telle procédure stockée revient à obtenir les résultats d'une requête 'select' du côté client. –

+0

Je devrais apprendre à propos de SQL Server un jour. On dirait que l'équivalent serait une fonction qui renvoie un refcursor, plutôt qu'une procédure avec un paramètre 'OUT', donc il peut être utilisé dans une requête de plan SQL? –

+0

MyPackage.GetQuestions est une procédure. par exemple. PROCEDURE GETQUETSIONS (sortie IN OUT MYPACKAGE.refcur_question, utilisateur IN VARCHAR2). Quand j'ai lié votre technique, je reçois des erreurs d'identifiants invalides –

0
/* 
    Create Sample Package in HR Schema 
*/ 

CREATE OR REPLACE PACKAGE PRINT_REF_CURSOR 
AS 
    PROCEDURE SP_S_EMPLOYEES_BY_DEPT (
     p_DEPARTMENT_ID IN INTEGER, 
     Out_Cur OUT SYS_REFCURSOR); 

END PRINT_REF_CURSOR;   

CREATE OR REPLACE PACKAGE BODY PRINT_REF_CURSOR 
AS 

    PROCEDURE SP_S_EMPLOYEES_BY_DEPT (
     p_DEPARTMENT_ID IN INTEGER, 
     Out_Cur OUT SYS_REFCURSOR) 
    AS 
    BEGIN 
     OPEN Out_Cur FOR 
      SELECT * 
      FROM EMPLOYEES 
      WHERE DEPARTMENT_ID = p_DEPARTMENT_ID; 
    EXCEPTION 
     WHEN NO_DATA_FOUND 
     THEN 
     DBMS_OUTPUT.Put_Line('SP_S_EMPLOYEES_BY_DEPT' || ',' || '-20000' || ','); 
     WHEN OTHERS 
     THEN 
     DBMS_OUTPUT.Put_Line('SP_S_EMPLOYEES_BY_DEPT' || ',' || '-20001' || ',');  
    END SP_S_EMPLOYEES_BY_DEPT;   

END PRINT_REF_CURSOR;  

/* 
    Fetch values using Ref Cursor and display it in grid. 
*/ 

var RC refcursor; 

DECLARE 
    p_DEPARTMENT_ID NUMBER; 
    OUT_CUR SYS_REFCURSOR; 

BEGIN 
    p_DEPARTMENT_ID := 90; 
    OUT_CUR := NULL; 

    PRINT_REF_CURSOR.SP_S_EMPLOYEES_BY_DEPT (p_DEPARTMENT_ID, OUT_CUR); 
    :RC := OUT_CUR; 

END; 
/
PRINT RC; 
/************************************************************************/ 
1

SQL Developer attrape automatiquement la sortie de l'exécution de vos procédures stockées.L'exécution de la procédure stockée directement de notre éditeur de procédure, vous pouvez voir ce comportement détaillé dans mon post ici

SQL Developer Tip: Viewing REFCURSOR Output

Maintenant, si vous voulez exécuter refcursor dans le cadre d'un bloc de Anon dans notre feuille de calcul SQL, vous pourrait faire quelque chose de similaire à ce

var rc refcursor 
exec :rc := GET_EMPS(30) 
print rc 

--where GET_EMPS() serait votre sp_GetQuestions ('OMG Ponies') appel. La commande PRINT envoie la sortie de la « requête » qui est couru par la procédure stockée, et ressemble à ceci:

anonymous block completed 
RC 
----------------------------------------------------------------------------------------------------- 
EMPLOYEE_ID FIRST_NAME   LAST_NAME     EMAIL      PHONE_NUMBER   HIRE_DATE     JOB_ID  SALARY  COMMISSION_PCT MANAGER_ID DEPARTMENT_ID 
----------- -------------------- ------------------------- ------------------------- -------------------- ------------------------- ---------- ---------- -------------- ---------- ------------- 
114   Den     Raphaely     DRAPHEAL     515.127.4561   07-DEC-94 12.00.00  PU_MAN  11000      100  30    
115   Alexander   Khoo      AKHOO      515.127.4562   18-MAY-95 12.00.00  PU_CLERK 3100      114  30    
116   Shelli    Baida      SBAIDA     515.127.4563   24-DEC-97 12.00.00  PU_CLERK 2900      114  30    
117   Sigal    Tobias     STOBIAS     515.127.4564   24-JUL-97 12.00.00  PU_CLERK 2800      114  30    
118   Guy     Himuro     GHIMURO     515.127.4565   15-NOV-98 12.00.00  PU_CLERK 2600      114  30    
119   Karen    Colmenares    KCOLMENA     515.127.4566   10-AUG-99 12.00.00  PU_CLERK 2500      114  30    

Maintenant, vous avez dit 10g. Si vous êtes en 12c, nous avons amélioré le moteur PL/SQL pour prendre en charge les résultats de curseur implicites. Cela devient un peu plus facile, pas plus de configurer le curseur, vous venez de faire un appel pour obtenir les données, comme documenté ici: http://docs.oracle.com/database/121/DRDAA/migr_tools_feat.htm#DRDAA230

+0

Je regardais cette fonction hier. C'est sympa, mais c'est un peu un PIA à faire car je ne peux pas simplement ouvrir une fenêtre "Run PL/SQL" Merci pour l'astuce 12c. Nous sommes toujours sur la 11G donc j'ai hâte de l'utiliser finalement. J'ai également réparé la mise en forme de votre message. Voir [Editing-help] (http://stackoverflow.com/editing-help) pour savoir comment je l'ai fait. –

+0

Donc, vous voulez une fenêtre 'run PL/SQL' qui saisira automatiquement la sortie, comme notre éditeur de procédure offres lors de l'exécution d'une seule unité? Ce n'est pas une mauvaise idée ... Je vais la faire tourner autour du groupe et voir où ça va. – thatjeffsmith

Questions connexes