Returning Oracle Stored Procedure Resultset in SSRS

What?
So I've spent a fun time googling and binging but still haven't found a simple and complete example of getting a resultset from an Oracle stored procedure and displaying this in SQL Server Reporting Services (SSRS). Well "non-productive" more than "fun" as most of the examples on the net are either half-complete or partially documented. So here goes...
  • Using Business Intelligence Development Studio v2008 (BIDS)
  • SQL Server Reporting Services v2008 R2 (SSRS)
  • Oracle SQL Developer v3 (you can use any equivalent, eg. SQL*Plus)

Why?
I think this is one of those very rare occasions that Microsoft people can say "it's so much easier using a Microsoft product to work with another Microsoft product" (ie "Seamless integration"). Yes, I'm trying to get an SSRS report to display the results from an Oracle stored procedure. I have a previous article describing a basic stored procedure in Oracle, this article aims to outline how to apply this to an SSRS 2008 R2 report.

How?
If you've googled this topic as much as I have, you'll note that everyone seems to be recommending using a cursor. I went through about 10 pages of google results without working out how to use these in SSRS and then resorted to my old methods of debugging. For those of you who don't know what a cursor is, you can find this info on another site as this article focuses on getting an Oracle stored procedure to work with SSRS.

Main Example:
My stored procedure will do the following:
  1. Get a student ID number based on the student username
  2. Get a student's names and date-of-birth based on the student ID number
Agenda Outline
Note: As simple as this sounds, this is not a five-minute job. Even with all your SQL scripts with backups of your datasets, each of these will need tweaking.
  1. Create your stored procedure in Oracle (and grant execute for your SSRS user)
  2. Add a data source to your SSRS report
  3. Add an SSRS input parameter
  4. Add a dataset
    1. Query type: Stored Procedure
    2. Refresh fields button
    3. Parameter name (oracle input sp variable) and Parameter value (ssrs input parameter)
    4. Fields (field name=ssrs reference, field source=oracle sp field name)

1. Create a stored procedure using a cursor for SSRS
copyraw
CREATE OR REPLACE PROCEDURE sp_get_studentdetails_from_ad (
        p_STUDENT_ADNAME IN varchar2,
	l_CURSOR OUT sys_refcursor
)
IS
BEGIN
    -- going to declare variables that are to be returned in SSRS but not
    -- mentioned in the above OUT variables:
    DECLARE
      p_STUDENT_REF number(8);
      p_STUDENT_DETAILS varchar2(255);
    
    -- putting a begin within otherwise I get warning errors (with an end!)
    BEGIN

    -- initial query to get me the student ID based on the inputted parameter
    SELECT
      student_accounts.student_id
    INTO
      p_STUDENT_REF
    FROM
      student_accounts
    WHERE
      student_accounts.student_username = p_STUDENT_ADNAME;

    -- opening cursor for the select query that I want to display in SSRS
    OPEN l_CURSOR FOR
      SELECT INITCAP(b.p_title)
       || ' '
       || INITCAP(b.p_forenames)
       || ' '
       || UPPER(b.p_surname)
       || ' ('
       || INITCAP(To_char(b.p_dob, 'DD-MON-YYYY'))
       || ')' "p_STUDENT_DETAILS",
       NVL(a.student_id, b.person_id) "p_STUDENT_REF"
      FROM
        student_accounts a
      INNER JOIN student_details b ON a.student_id = b.person_id
      WHERE a.student_id = p_STUDENT_REF;

    -- ending that second begin I had after my variable declaration
    END;

    EXCEPTION
        WHEN OTHERS THEN
             RAISE_APPLICATION_ERROR (-20001, p_STUDENT_ADNAME || ':$:' || SQLERRM, TRUE);

END sp_get_studentdetails_from_ad;
  1.  CREATE OR REPLACE PROCEDURE sp_get_studentdetails_from_ad ( 
  2.          p_STUDENT_ADNAME IN varchar2, 
  3.      l_CURSOR OUT sys_refcursor 
  4.  ) 
  5.  IS 
  6.  BEGIN 
  7.      -- going to declare variables that are to be returned in SSRS but not 
  8.      -- mentioned in the above OUT variables: 
  9.      DECLARE 
  10.        p_STUDENT_REF number(8)
  11.        p_STUDENT_DETAILS varchar2(255)
  12.   
  13.      -- putting a begin within otherwise I get warning errors (with an end!) 
  14.      BEGIN 
  15.   
  16.      -- initial query to get me the student ID based on the inputted parameter 
  17.      SELECT 
  18.        student_accounts.student_id 
  19.      INTO 
  20.        p_STUDENT_REF 
  21.      FROM 
  22.        student_accounts 
  23.      WHERE 
  24.        student_accounts.student_username = p_STUDENT_ADNAME; 
  25.   
  26.      -- opening cursor for the select query that I want to display in SSRS 
  27.      OPEN l_CURSOR FOR 
  28.        SELECT INITCAP(b.p_title) 
  29.         || ' ' 
  30.         || INITCAP(b.p_forenames) 
  31.         || ' ' 
  32.         || UPPER(b.p_surname) 
  33.         || (' 
  34.         || INITCAP(To_char(b.p_dob, 'DD-MON-YYYY')) 
  35.         || ')' "p_STUDENT_DETAILS", 
  36.         NVL(a.student_id, b.person_id) "p_STUDENT_REF" 
  37.        FROM 
  38.          student_accounts a 
  39.        INNER JOIN student_details b ON a.student_id = b.person_id 
  40.        WHERE a.student_id = p_STUDENT_REF; 
  41.   
  42.      -- ending that second begin I had after my variable declaration 
  43.      END; 
  44.   
  45.      EXCEPTION 
  46.          WHEN OTHERS THEN 
  47.               RAISE_APPLICATION_ERROR (-20001, p_STUDENT_ADNAME || ':$:' || SQLERRM, true)
  48.   
  49.  END sp_get_studentdetails_from_ad; 
Permissions on this SP
Might need to give permission for your SSRS user (specified credentials in data source) to run this stored procedure.
copyraw
CREATE PUBLIC SYNONYM sp_get_studentdetails_from_ad FOR base_table_owner.sp_get_studentdetails_from_ad;
GRANT EXECUTE ON sp_get_studentdetails_from_ad TO my_ssrs_user;
  1.  CREATE PUBLIC SYNONYM sp_get_studentdetails_from_ad FOR base_table_owner.sp_get_studentdetails_from_ad; 
  2.  GRANT EXECUTE ON sp_get_studentdetails_from_ad TO my_ssrs_user; 
Notes:
  • No "SELECT ... INTO ..." on the second query which is the one that will return my columns.
  • Two output fields are expected to be returned: "p_STUDENT_DETAILS" and "p_STUDENT_REF".

2. Add a datasource
Nothing different to your usual method of connecting to a data source, I just added this section to say that my data source is type "Oracle" and NOT ODBC or OLEDB. Unicode=true and my user is a specific read-only user.

3. Add an SSRS parameter
Idem as in just specify a parameter as you would for any usual SSRS report. (Ignore my 2nd and 3rd SSRS parameters in my example as I didn't end up using them)

4. Add a dataset
Follow these steps carefully. I've added some screenshot images to help and highlighted areas which you should ensure are correct (or which applies to your report)

4a. Add a dataset: query type "Stored Procedure"
Click on the radio button when adding your dataset and then select the stored procedure from the dropdown list.

4b. Add a dataset: the "Refresh fields..." button
Click on the "Refresh fields..." button so that you can define the query parameters.

4c. Add a dataset: the "Parameter Names"
Under "Parameter Name" type the exact same name for the input variable used in your Oracle stored procedure (in my example: p_STUDENT_ADNAME). Under "Parameter Value" type the exact same name of your SSRS parameter prefixed with a square bracket and the at sign and then suffixed with a closing square bracket (in my example: [@StudentReference]).

Adding a dataset for an Oracle stored procedure
4d. Add a dataset: returned "Fields"
These is where you "map" the variables to the oracle returned variables.
Adding a dataset for an Oracle stored procedure

Debug Testing
"Process of elimination" is possibly my favorite and most reliable way of figuring out what's wrong. Here are some suggestions:
  • Check your Oracle stored procedure compiles without warnings in SQL Developer (or SQL*Plus, etc.)
  • Hardcode your parameters in the SSRS report with actual values that would have been submitted.
  • Create the most basic report you can with the data you're working with just so you can get used to how this works.
  • IMPORTANT! Make sure you have prefixed the parameter name with an at sign and surrounded the input parameter between square parameters, example: [@StudentReference]. Fixing this resolved all 3 issues below!!!
Encountered Issues
  • ORA-01403 no data found & ORA-06512 something else - Fixed by specifying the query parameter properly (ex: Parameter name = p_STUDENT_ADNAME, Parameter Value = [@StudentReference] - NOTE THE SQUARE BRACKETS FOR PARAMETER VALUE)
  • PLS-00306: Wrong number or types of arguments in call - Fixed this by double-checking the parameters. Input variable has to be listed in the "dataset properties" > "query parameter values" under "Parameter Name" and then the SSRS parameter value (eg. "[@my_ssrs_parameter]").
  • Internal .Net Framework Data Provider error 30 - Wrong datatypes I was told but found this is just how I was calling the parameter. I declared these in the stored procedure but the fix in the end was referring to the Query Parameter Value properly.
  • IMPORTANT! Make sure you have prefixed the parameter name with an at sign and surrounded the input parameter between square parameters, example: [@StudentReference]. I cannot stress enough how much delay this minor detail caused!!!
  • No data displays in SSRS but procedure compiled without warnings - My fault really, the field name aliases specified in my second select query (the one preceded with "open cursor for") didn't match my SSRS report field name mapping.

Done!
Well almost as you still need to design your report. At least this article should have got you to the part where you're simply specifying what data displays where. It took me 4 days to figure this out then document it. Here's to hoping that this saves you some time!

Category: SQL Server Reporting Services :: Article: 411

Credit where Credit is Due:


Feel free to copy, redistribute and share this information. All that we ask is that you attribute credit and possibly even a link back to this website as it really helps in our search engine rankings.

Disclaimer: Please note that the information provided on this website is intended for informational purposes only and does not represent a warranty. The opinions expressed are those of the author only. We recommend testing any solutions in a development environment before implementing them in production. The articles are based on our good faith efforts and were current at the time of writing, reflecting our practical experience in a commercial setting.

Thank you for visiting and, as always, we hope this website was of some use to you!

Kind Regards,

Joel Lipman
www.joellipman.com

Related Articles

Joes Revolver Map

Accreditation

Badge - Certified Zoho Creator Associate
Badge - Certified Zoho Creator Associate

Donate & Support

If you like my content, and would like to support this sharing site, feel free to donate using a method below:

Paypal:
Donate to Joel Lipman via PayPal

Bitcoin:
Donate to Joel Lipman with Bitcoin bc1qf6elrdxc968h0k673l2djc9wrpazhqtxw8qqp4

Ethereum:
Donate to Joel Lipman with Ethereum 0xb038962F3809b425D661EF5D22294Cf45E02FebF
© 2024 Joel Lipman .com. All Rights Reserved.