2010-08-19 661 views
15

En MS SQL Server, si deseo verificar los resultados de un procedimiento Almacenado, podría ejecutar lo siguiente en Management Studio.¿Cómo obtiene resultados muy formateados de un procedimiento de Oracle que devuelve un cursor de referencia?

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

La salida en el panel de resultados podría verse así.

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) 

No es necesario escribir bucles o instrucciones PRINT.

Para hacer lo mismo en Oracle podría ejecutar el siguiente bloque anónimo en 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; 

Este salidas como

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 

Así que la versión de SQL tiene 1 línea y el oráculo tiene 18 y la salida es fea Se agrava si hay muchas columnas y/o los datos son numéricos.

Lo que es extraño para mí de esto es que si escribo esta declaración, ya sea en el estudio de administración de SQL Developer o ...

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

Los resultados son bastante similares. Esto me hace sentir que me falta una técnica o uso la herramienta incorrecta.

Respuesta

16

Si GetQuestions es una función que devuelve un refcursor, que parece ser lo que tiene en la versión de SQL Server, a continuación, en lugar usted puede ser capaz de hacer algo como esto:

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

O si lo necesita en un bloque PL/SQL, puede usar la misma selección en un cursor.

En su lugar, también puede hacer que la función produzca las declaraciones dbms_output para que siempre estén disponibles para la depuración, aunque eso agrega un poco de sobrecarga.

Editar

Hmmm, no estoy seguro de que es posible cast() la refcursor regresado a un tipo utilizable, a menos que esté dispuesto a declarar su propio tipo (y una mesa de ese tipo) fuera del paquete. Usted puede hacer esto, sin embargo, sólo para volcar los resultados:

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; 

Y puede utilizar el resultado de la llamada en otro procedimiento o función; es solo llegar a PL/SQL que parece ser un poco complicado.

Editado para agregar: Con este enfoque, si se trata de un procedimiento que puede hacer esencialmente la misma cosa:

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

La versión de SQL Server probablemente no sea una función. En SQL Server, los procedimientos almacenados que retornan como resultados solo tienen sentencias 'select' que no están unidas a un cursor. Obtener los resultados de la ejecución de dicho procedimiento almacenado es lo mismo que obtener los resultados de una consulta 'select' en el lado del cliente. –

+0

Debería aprender sobre SQL Server algún día. Parece que el equivalente sería una función que devuelve un refcursor, en lugar de un procedimiento con un parámetro 'OUT', por lo que se puede utilizar en una consulta del plan SQL. –

+0

MyPackage.GetQuestions es un procedimiento. p.ej. GETQUETSIONS DE PROCEDIMIENTO (salida IN OUT MYPACKAGE.refcur_question, usuario IN VARCHAR2). Cuando até su técnica recibo errores de identificador no válido –

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 capta automáticamente la salida de la ejecución de los procedimientos almacenados.Ejecutar el procedimiento almacenado directamente desde nuestro editor de procedimiento, se puede ver este comportamiento detallado en mi post aquí

SQL Developer Tip: Viewing REFCURSOR Output

Ahora, si desea ejecutar el refcursor como parte de un bloque de anon en nuestra hoja de trabajo SQL, podría hacer algo similar a esta

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

GET_EMPS --Si llegara a ocurrir() serían sus sp_GetQuestions ('OMG potros') llamada. El comando PRINT envía la salida de la 'consulta' que se corrió a través del procedimiento almacenado, y se ve así:

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    

Ahora, usted ha dicho 10g. Si está en 12c, hemos mejorado el motor PL/SQL para que admita resultados de cursor implícitos. Así que esto se vuelve un poco más fácil, sin configurar el cursor, solo realiza una llamada para obtener los datos, como se documenta aquí: http://docs.oracle.com/database/121/DRDAA/migr_tools_feat.htm#DRDAA230

+0

En realidad estaba viendo esta característica ayer. Es bueno, pero como una especie de PIA, no puedo simplemente abrir una ventana "Ejecutar PL/SQL". Gracias por la sugerencia de 12c. Todavía estamos en 11G, así que espero usarlo eventualmente. También arreglé el formato de tu publicación. Consulte [Editing-help] (http://stackoverflow.com/editing-help) para obtener información sobre cómo lo hice –

+0

. Así que desea una ventana 'ejecutar PL/SQL' que autoagregue el resultado, como nuestro Editor de procedimientos ofertas cuando se ejecuta una sola unidad? No es una mala idea ... Lo patearé alrededor del grupo y veré a dónde va. – thatjeffsmith

Cuestiones relacionadas