Solved

How to return OUT variable value from Oracle stored procedure to .NET (C#) code?

Posted on 2008-10-19
19
9,490 Views
Last Modified: 2013-12-17
I'm working on an application which may use multiple database types (MySQL, MSSQL, Oracle). Since the queries (and mainly stored procedures calls) are different on these databases the calls are defined in XML (as strings).
E.g. (for MySQL) I call stored procedure this way:
set @id=0; call insert_record(@id, '{0}'); select @id;

I call this within C# code using .ExecuteScalar() - the result is dataset with 1 column and 1 row (ID of the newly inserted row). Procedure insert_record is defined this way:

CREATE PROCEDURE `insert_record`(OUT id INT, p_value VARCHAR(150))
BEGIN
  INSERT INTO data (value)
    VALUES (p_value);
  SET id = LAST_INSERT_ID();
END;

I really don't want to change the C# code because of Oracle implementation and therefore I'm looking for a way how to execute a stored procedure and return its OUT parameter within a dataset.

I'm using the Oracle .NET library (Oracle.DataAccess.Client) provided by Oracle.

Thanks for your help guys :).
0
Comment
Question by:petr_hlucin
  • 11
  • 8
19 Comments
 
LVL 48

Expert Comment

by:schwertner
ID: 22785916
The statement

  SET id = LAST_INSERT_ID();

is not PL/SQL statement. Possibly it comes from other DB procedural language.

in Oracle you can use another solution.

1. define a sequence
2. use nextval pseudocolumn to insert the id:

CREATE PROCEDURE insert_record (OUT id INT, p_value VARCHAR(150))
BEGIN
  id := seqience_name.nextval;
  INSERT INTO data (id, value)
              VALUES (id, p_value);
END;
0
 
LVL 48

Expert Comment

by:schwertner
ID: 22785940
Bad syntax:

CREATE PROCEDURE insert_record     ( id OUT INT,       p_value VARCHAR(150))
BEGIN
      id := sequence_name.nextval;
      INSERT INTO data (id, value)
                   VALUES (id, p_value);
END;
/
0
 
LVL 4

Author Comment

by:petr_hlucin
ID: 22806499
Sorry, I didn't express myself clearly enough. The code I've posted is MySQL code. I need to do the same in Oracle. I know how to create the procedure in Oracle but what I'd really like to know is how to execute the procedure so it returns a dataset containing just 1 record (newly created ID - basically any variable which is used within the procedure).

Anybody?
0
Three Reasons Why Backup is Strategic

Backup is strategic to your business because your data is strategic to your business. Without backup, your business will fail. This white paper explains why it is vital for you to design and immediately execute a backup strategy to protect 100 percent of your data.

 
LVL 48

Expert Comment

by:schwertner
ID: 22807087
You have to know how this ID is produced.
I most cases Oracle uses sequences (integer number generators, created
ad hoc by the programmers).

Look at this:

CREATE PROCEDURE insert_record     ( id OUT INT,       p_value VARCHAR(150))
BEGIN
      id := sequence_name.nextval;        INSERT INTO data (id, value)
                   VALUES (id, p_value);
END;
/


id := sequence_name.nextval; retrieves the next number from the sequence.
Additionally it is stored in the OUT parameter what possibly is a error.
So I will fix the code:


CREATE PROCEDURE insert_record     ( id OUT INT,       p_value VARCHAR(150))
   v_id   INTEGER;
BEGIN
      v_id := sequence_name.nextval;        
     INSERT INTO data (id, value)
                   VALUES (id, p_value);
     id := v_id;
END;
/

Now you have to call the procedure and to get the out value.
Of course you have to provide the programatical tool
to produce the ids (I suggest Oracle sequence).
Look in the net and find example how to create it.

0
 
LVL 4

Author Comment

by:petr_hlucin
ID: 22807878
Please disregard the code I've provided in previous posts. I'm just looking for a way how to export OUTPUT variable of the procedure to a dataset. I know how sequences and all this staff work.

So I'm looking for a way how to do equivalent of this code (MySQL) in Oracle:

set @id=0; call proc(@id); select @id;

where proc is a stored procedure which has just 1 output parameter. What proc does doesn't have anything to do with my problem.

0
 
LVL 48

Expert Comment

by:schwertner
ID: 22813488
Use the common way.

If you decide to use PL/SQL (there are also C, Java, VB interfaces), then
using anonymous block:

DECLARE
      v_id     NUMBER;
      v_value := VARCHAR2(4000);
BEGIN
      v_valie := 'Some value';
      insert_record  ( v_id,       p_value)
      dbms_output.put_line (v_id);
END;
/
     
0
 
LVL 4

Author Comment

by:petr_hlucin
ID: 22822920
This one returns null when executed using ExecuteScalar() (doesn't return any record when executed by ExecuteReader()).
0
 
LVL 48

Expert Comment

by:schwertner
ID: 22829937
CREATE PROCEDURE insert_record     ( id OUT INT,       p_value VARCHAR(150))
   v_id   INTEGER;
BEGIN
      v_id := sequence_name.nextval;        
     INSERT INTO data (id, value)
                   VALUES (v_id, p_value);
     id := v_id;
EXCEPTION
WHEN OTHERS THEN
    dbms_output.put_line(substr(sqlerrm,1,254));
    id := -111;
END;
/


First check it with PL/SQL:

set serveroutput on

DECLARE
      v_id     NUMBER;
      v_value := VARCHAR2(4000);
BEGIN
      v_valie := 'Some value';
      insert_record  ( v_id,       p_value)
      dbms_output.put_line (v_id);
END;
/

0
 
LVL 4

Author Comment

by:petr_hlucin
ID: 22886412
Unfortunatelly dbms_output.put_line() writes to kind of standard output but not to the output dataset.
0
 
LVL 48

Expert Comment

by:schwertner
ID: 22893176
This is only to check if it really returns the value
and if there are exceptions that prevent the
execution.
After you make sure that the value is really returned
by the stored procedure you con move the focus
of your efforts to the interface with the MS stuff.
0
 
LVL 4

Author Comment

by:petr_hlucin
ID: 22902764
I know that the correct value is returned as output variable. What I'd like to do is return this value as output dataset.

Current workaround which I use is:
- store this value to a package variable
- select this value

This solution is almost OK however I need to execute the SQL command twice. Does anybody know how to do this at once?
0
 
LVL 48

Expert Comment

by:schwertner
ID: 22903318
These worarounds will not hel you because package variables are created for every session and
so every session (assuming you are not using it in one session) will create its own copy of the variable.
But possibly I am wrong and you work in one session. In this case it is possible to use associative arrays (former PL/SQL tables or normally speaking an array).
So to use multisession acces to the resul one possible solution is to store the values in a regulat table.
0
 
LVL 4

Author Comment

by:petr_hlucin
ID: 22917556
In this case I execute both commands within one session (at least I hope that ODP doesn't change the session while pointer to instance of SqlCommand exists and all commands executed while SqlCommand instance exists are sent within one session). So the current problem is how to execute these 2 commands at once. Anybody?
0
 
LVL 48

Expert Comment

by:schwertner
ID: 22923658
Take experiment that will show the truth.
0
 
LVL 4

Author Comment

by:petr_hlucin
ID: 22929440
OK, will inform. Anyway I'd be very happy if somebody came up with a solution which wouldn't require executing 2 queries.
0
 
LVL 48

Expert Comment

by:schwertner
ID: 22942204
Using PL/SQL table that can store unlimited entries and can be returned as record set in Oracle environmet.
0
 
LVL 48

Expert Comment

by:schwertner
ID: 22942219
Using PL/SQL table that can store unlimited entries and can be returned as record set in Oracle environmet.
0
 
LVL 48

Accepted Solution

by:
schwertner earned 500 total points
ID: 22942242
Using PL/SQL table that can store unlimited entries and can be returned as record set in Oracle environmet.
0
 
LVL 4

Author Comment

by:petr_hlucin
ID: 23061136
OK, to close this - there are several solutions to this problem but none of them can be executed using 1 query. I accept schwertner's solution but I've used mine.
0

Featured Post

Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Title # Comments Views Activity
API v SOA 8 37
removing unwanted rows from an sql server ranked table 13 34
global Variable - 2 functions in powershell 1 19
SQL Select Query help 1 34
Why is this different from all of the other step by step guides?  Because I make a living as a DBA and not as a writer and I lived through this experience. Defining the name: When I talk to people they say different names on this subject stuff l…
From implementing a password expiration date, to datatype conversions and file export options, these are some useful settings I've found in Jasper Server.
Via a live example, show how to restore a database from backup after a simulated disk failure using RMAN.
This video explains what a user managed backup is and shows how to take one, providing a couple of simple example scripts.

685 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question