I have an Oracle Stored Procedure that has a return cursor that I would like to access using EF 5. I have read multiple question from the site but still can not get it to work.
This is my oracle stored procedure:
CREATE OR REPLACE PROCEDURE GETINFO
(
"StoreId" IN varchar2 , OUT_RESULT OUT SYS_REFCURSOR
)
IS
sqlstmt VARCHAR2(2000);
BEGIN
sqlstmt := 'SELECT v."StoreId", v."ProductCategory" "Product", v."ProductId"
FROM SUPERMARKET v WHERE v."StoreId"='||"StoreId";
OPEN Out_Result FOR sqlStmt;
END GETINFO;
According to Oracle documentation, to access SYS_REFCURSOR, I have to explicitly declare it in my App.config, which I did:
<oracle.dataaccess.client>
<settings>
<oracle.manageddataaccess.client>
<version number="*">
<StoredProcedure schema="MYSCHEMA" name="GETINFO">
<refCursor name="OUT_RESULT">
<bindInfo mode="Output" />
<metadata columnOrdinal="0" columnName="StoreId" providerType="NUMBER" />
<metadata columnOrdinal="1" columnName="Product" providerType="Varchar2" />
<metadata columnOrdinal="2" columnName="ProductId" providerType="Varchar2" />
</refCursor>
</StoredProcedure>
</version>
</oracle.manageddataaccess.client>
</settings>
</oracle.dataaccess.client>
There may be other pieces hidden from Oracle documentation regarding meta data that I may have to include in the App.Config. As a result, I am still not able to access my specific SYS_REFCURSOR because when I clicked on Get Column Information, I got nothing and there was nothing in the complex combo box. According to Oracle, I should have to structure of the SYS_REFCURSOR to refer to.
My Entity Framework is 5.0, I use VS 2012.
What else do I need to include in the meta data?
My underlying SUPERMARKET table structure is:
Name Null Type
--------------- ---- ------------
StoreId NUMBER
ProductCategory VARCHAR2(20)
ProductId VARCHAR2(20)
Related
I'm trying to find better approach for selecting from REFCURSOR. Let's say there is a such function:
CREATE OR REPLACE FUNCTION get_batches_to_export(p_batch_type varchar2 := NULL)
RETURN SYS_REFCURSOR
AS
o_cursor SYS_REFCURSOR;
BEGIN
OPEN o_cursor FOR
SELECT batch_id
FROM batches
WHERE batch_type = p_batch_type OR p_batch_type IS NULL;
RETURN o_cursor;
END;
Now I need to select content from this table using requral select (it is limitation of client application - NiFi usign JDBC connection - it supports only scalar types to be returned, deseralization of REFCURSOR fails; also direct select from source table is not possible)
I found this select, it creates XML from REFCURSOR and then extracts values from this XML:
SELECT extractvalue(value(batches_list),'ROW/BATCH_ID') batch_id
FROM table(xmlsequence(get_batches_to_export())) batches_list
Any idea how to avoid the XML part (the xmlsequence, extractvalue and value function calls)? There is also limitation I cannot create any other helper data types or objects - only select can be used.
I would like to know how can I return a nested table from a stored procedure in oracle to consume in my .net client.
Basically I used the following format for creating nested table :
TYPE changes IS RECORD(
col1 VARCHAR2(20),
col2 VARCHAR2(20),
col3 VARCHAR2(20)
);
TYPE collection is table of changes;
I'm populating this with values in stored procedure logic.
Now I want to return these values for my .net client.
Can we try to dump nested tables values to cursor and return back. If yes then how ?
First off, if using ODP.net then know that you can directly pass collection types between a procedure and your UI. It is finicky, but it works.
If you want to simply dump a collection into a cursor to be returned, then look at the TABLE() function. In your example you could pass back a ref_cursor for the UI to traverse using something like (forgive any minor syntax glitches - I'm away from my database at the moment):
FUNCTION collection_to_cursor
return sys_refcursor
IS
p_cursor sys_refcursor;
p_change changes;
BEGIN
Open p_cursor for (
SELECT col1, col2, col3
FROM TABLE(p_change));
RETURN p_cursor;
end;
You could use a ref cursor, something along the lines of
DECLARE
lt_collection collection := collection();
lrc_collection SYS_REFCURSOR;
BEGIN
lt_collection := f_populate_collection_somehow;
OPEN lrc_collection
SELECT col1
,col2
,col3
FROM TABLE(CAST(lt_collection AS collection));
END;
.NET can then retrieve the data from the ref cursor, I'm not sure of the details of how this is done.
There is some good further information on using ref cursors or associative arrays
here
Please note, I am not conversant with .NET, so I am writing this literally to your question "how can I return a nested table from a stored procedure in oracle".
I am not sure about the "to consume in my .net client" portion, as I am not sure if a returned record type/table type can directly be used in .net code.
I did some research and what I learnt is that there is no direct support of record type in any oracle client interface. What people generally do is to create a wrapper procedure around the returned table type from function to convert it into a ref cursor and use the ref cursor in custom code.
CREATE OR REPLACE TYPE changes AS OBJECT(
col1 VARCHAR2(20),
col2 VARCHAR2(20),
col3 VARCHAR2(20)
);
CREATE OR REPLACE TYPE collection is table of changes;
CREATE OR REPLACE PACKAGE test_pkg AS
FUNCTION test_fn RETURN collection;
END test_pkg;
CREATE OR REPLACE PACKAGE BODY test_pkg
AS
FUNCTION test_fn RETURN collection AS
l_collection collection;
BEGIN
l_collection := collection();
l_collection.EXTEND;
l_collection(l_collection.LAST) := changes('Subhasis','Mukherjee','Male');
RETURN l_collection;
END test_fn;
END test_pkg;
SELECT * FROM table(test_pkg.test_fn)
col1 col2 col3
----------- ------------- --------------
Subhasis Mukherjee Male
i am trying to work with stored procedure written inside a package but i am not able to access:
Runtime: Failed to retrieve data with procedure :
XXMOB_LOGIN_AN.login_prc
In the adapter JS:
function procedure2(p_usrname,p_password) {
return WL.Server.invokeSQLStoredProcedure({
procedure : "XXMOB_LOGIN_AN.login_prc",
parameters : []
});
}
The procedure:
create or replace PACKAGE XXMOB_LOGIN_AN AUTHID CURRENT_USER AS
Procedure login_prc (
p_usrname IN VARCHAR2,
p_password IN VARCHAR2,
p_person_id OUT VARCHAR2,
p_groups_id OUT VARCHAR2,
p_person_login OUT VARCHAR2,
p_person_role OUT VARCHAR2,
p_user_id OUT VARCHAR2,
p_welcome OUT VARCHAR2,
p_return OUT VARCHAR2,
P_return_message out varchar2
);
END XXMOB_LOGIN_AN;
In the adapter XML:
<?xml version="1.0" encoding="UTF-8"?>
<wl:adapter name="strprc"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:wl="http://www.ibm.com/mfp/integration"
xmlns:sql="http://www.ibm.com/mfp/integration/sql">
<displayName>strprc</displayName>
<description>strprc</description>
<connectivity>
<connectionPolicy xsi:type="sql:SQLConnectionPolicy">
<!-- Example for using a JNDI data source, replace with actual data source name -->
<!-- <dataSourceJNDIName>java:/data-source-jndi-name</dataSourceJNDIName> -->
<!-- Example for using MySQL connector, do not forget to put the MySQL connector library in the project's lib folder -->
<dataSourceDefinition>
<driverClass>oracle.jdbc.driver.OracleDriver</driverClass>
<url>jdbc:oracle:thin:#</url>
<user>***</user>
<password>***</password>
</dataSourceDefinition>
</connectionPolicy>
</connectivity>
<!-- Replace this with appropriate procedures -->
<procedure name="procedure2"/>
</wl:adapter>
As mentioned in the comments, Worklight does not support the out parameter in SQL adapters. See this question: IBM Worklight - How to get OUT parameter when invoking a stored procedure?
The question I linked you to also contains an answer providing an elaborate workaround if you wish the try it (basically, override Worklight and implement it in Java code).
I am new to Oracle and Stored Procedures. I just would like to know if its possible, like in SQL Server, to return a recordset with Field Names to an extern program. I read some documentations but I'm not sure if I'm on the right track. When I use Sys_Refcursor I can only return one Field and not as many as I would like to.
I need to return multiple Field Names and I have one input parameter.
In the documentation of the program, i have an example for SQL Server and I would like to have the same for my Oracle Stored Procedure:
Use
Go
Set Ansi_Nulls ON
Go
Alter Procedure
#InputLocation Varchar(255)
As
Begin
Set Nocount On;
select FirstName as '#FirstName', Company as '#Company' from dbo.company where Location = #InputLocation
End
Are there any suggestions how I can do that? If you need some additional informations just let me know. Thanks.
/edit:
My sample Code (without using the Input Parameter in the first step, just for generating Output to see if it works):
create or replace
PROCEDURE TEST_PROZEDUR1 (
Input_Location IN Varchar2,
First_Name OUT SYS_Refcursor,
Company OUT Sys_Refcursor) IS
BEGIN
open First_Name For Select FirstName from dbo.company;
open Company For Select Company from dbo.company;
END TEST_PROZEDUR1;
The programming models used for PL/SQL and TSQL are different. Where you might return a recordset in TSQL, in PL/SQL you would return a cursor. A cursor is just a pointer to an SQL statement which is opened and can be read. It is not limited to returning a single column. Roughly, the PL/SQL equivalent of your TSQL procedure above would be something like:
CREATE OR REPLACE FUNCTION GET_INPUT_LOCATION(pinInput_location IN VARCHAR2(255))
RETURN SYS_REFCURSOR
IS
cCursor SYS_REFCURSOR;
BEGIN
OPEN cCursor FOR
SELECT FIRSTNAME,
COMPANY
FROM COMPANY
WHERE LOCATION = pinInput_location;
RETURN cCursor;
END GET_INPUT_LOCATION;
The caller would then invoke this function as:
DECLARE
cCursor SYS_REFCURSOR;
strFirstname COMPANY.FIRSTNAME%TYPE;
strCompany COMPANY.COMPANY%TYPE;
BEGIN
cCursor := GET_INPUT_LOCATION('SOMEWHERE OVER THE RAINBOW, INC.');
FETCH cCursor
INTO strFirstname,
strCompany;
CLOSE cCursor;
END;
However, I probably wouldn't code it this way. If COMPANY.LOCATION is unique then you're going to a lot of trouble to return a cursor which the caller will need to remember to close when they're done with it, which they may forget to do. Instead, I'd just return the FIRSTNAME and COMPANY fields using output parameters; e.g.
CREATE OR REPLACE PROCEDURE GET_INPUT_LOCATION
(pinInput_location IN VARCHAR2(255),
poutFirst_name OUT COMPANY.FIRSTNAME%TYPE,
poutCompany OUT COMPANY.COMPANY%TYPE)
IS
cCursor SYS_REFCURSOR;
BEGIN
SELECT FIRSTNAME,
COMPANY
INTO poutFirst_name,
poutCompany
FROM COMPANY
WHERE LOCATION = pinInput_location;
END GET_INPUT_LOCATION;
Share and enjoy.
I have a working plsql oracle stored procedure (i have tested it in plsql and it return the correct value(s)):
PROCEDURE FetchCode(code OUT NUMBER) IS
BEGIN
SELECT MYSEQ.NEXTVAL INTO code FROM DUAL;
END FetchCode;
and a visual studio solution using entity framework.
The csdl file contains
<FunctionImport Name="FETCHCODE" ReturnType="Collection(Decimal)">
<Parameter Name="CODE" Mode="Out" Type="Decimal" />
</FunctionImport>
I have been successful in pulling the above function in to entity but when i try the "Get Column Information" button, I receive the "The selected stored procedure returns no columns." message.
Under edit function import I can see that it:
Returns a Collection of
Scalars: Decimal
The data type is set to "Number" and the direction is "Output".
Can anyone help explain why a sp like this would work on plsql but not in visual studio?
Try
CREATE or REPLACE FUNCTION FetchCode IS
RETURN NUMBER
DECLARE
code NUMBER(10);
BEGIN
SELECT MYSEQ.NEXTVAL INTO code FROM DUAL;
RETURN code;
END FetchCode;
Usually a function in Oracle is capable of returning values unlike Procedures where the output is accessed via the OUT or IN OUT variables.
Try the following
CREATE OR REPLACE PROCEDURE FetchCode
(
results_ OUT SYS_REFCURSOR
) IS
BEGIN
OPEN results_ FOR
SELECT MYSEQ.NEXTVAL As Code FROM DUAL;
END FetchCode;