views:

83

answers:

1

EDIT: Clarified the question

In MS SQL Server if I want to check the results from a Stored procedure I might execute the following in Management Studio.

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

The output in the results pane might look like this.

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 need to write loops or PRINT statements.

To do the same thing in Oracle I might execute the following anonymous block in 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;

This outputs like

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

So the SQL version has 1 line and the oracle has 18 and the output is ugly. Its exacerbated if there are a lot of columns and/or the data is numeric.

What's odd to me about this is that if I write this statement in either SQL Developer or Management studio...

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

The results are fairly similar. This makes me feel like I'm either missing a technique or using the wrong tool.

EDIT: Thanks to Alex I added a function to the package

FUNCTION GetQuestionsForPrint (user in varchar2)
  RETURN MYPACKAGE.refcur_question
AS  

    OUTPUT MYPACKAGE.refcur_question;

BEGIN 

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


  RETURN OUTPUT;
END;

Then from SQL Developer I can execute and it works just the way I wanted it to.

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

UPDATE The following is way better.

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

Now if I could just go two years back in time when I started writing these packages...

+3  A: 

If GetQuestions is a function returning a refcursor, which seems to be what you have in the SQL Server version, then rather you may be able to do something like this:

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

Or if you need it in a PL/SQL block then you can use the same select in a cursor.

You can also have the function produce the dbms_output statements instead so they're always available for debugging, although that adds a little overhead.

Edit

Hmmm, not sure it's possible to cast() the returned refcursor to a usable type, unless you're willing to declare your own type (and a table of that type) outside the package. You can do this though, just to dump the results:

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;

And you can use the result of the call in another procedure or function; it's just getting to it outside PL/SQL that seems to be a little tricky.

Edited to add: With this approach, if it's a procedure you can do essentially the same thing:

var r refcursor;
exec mypackage.getquestions(:r, 'OMG Ponies');
print r;
Alex Poole
The SQL Server version probably is not a function. In SQL Server, stored procedures that return set like results just have `select` statements that are not bound to a cursor. Getting the results of the execution of such a stored procedure is the same as getting the results from a `select` query on the client side.
Shannon Severance
I should learn about SQL Server one day. Seems like the equivalent would be a function that returns a refcursor though, rather than a procedure with an `OUT` parameter, so it can be used in a query from plan SQL?
Alex Poole
MyPackage.GetQuestions is a procedure. e.g. PROCEDURE GETQUETSIONS(output IN OUT MYPACKAGE.refcur_question, user IN VARCHAR2). When I tied your technique I get invalid identifier errors
Conrad Frix
I was thinking you could make it a function instead; `FUNCTION GETQUESTIONS(user IN VARCHAR2) RETURNS refcur_question`. But you may not be able to modify it; and from memory you might have to define the return type (`refcur_question`) at schema level, not inside the package, but it's been a while...
Alex Poole
@Alex You rock.
Conrad Frix
If you are keeping the existing procedure, try `exec mypackage.getquestions(:r, 'OMG Ponies');` instead of having the extra function to do the conversion. I'd fixated on a function because I thought it would cast, but as it doesn't a procedure is fine (and possibly more 'standard'). So you still have 3 lines replacing your original 18 *8-)
Alex Poole
Alex that worked and what I was looking for but the function was interesting as well
Conrad Frix