问题
I want to create a procedure or function in oracle that returns more than one row of different types to my application. I found some examples on the internet but i can't get it to work...
Example: I created a custom type in oracle:
create type proc_selectall is object
(Mjera varchar2(50),
Status number(10,0),
Naziv varchar2(50),
Stat number(10,0));
Then:
create type ret_selectall is table of proc_selectall;
Then created function:
create or replace function fsp_SelectAll return ret_selectall
is
l_ret_selectall ret_selectall := ret_selectall();
n integer := 0;
BEGIN
for r in(SELECT JEDINICAMJERE.Mjera,
JEDINICAMJERE.Status,
KATEGORIJE.Naziv,
KATEGORIJE.Status as Stat
FROM JEDINICAMJERE, KATEGORIJE)
loop
l_ret_selectall.extend;
n := n + 1;
l_ret_selectall(n) := proc_selectall(r.Mjera, r.Status, r.Naziv, r.Stat);
end loop;
return l_ret_selectall;
END;
When I type this line:
select * from table (fsp_SelectAll)
I get a nice and expected output:
MJERA | STATUS | NAZIV | STAT
tr 0 name1 1
fd 1 name2 1
ds 1 name3 0
.....
Later i tried to get those values in my app. I tried something like this:
//cmd.Parameters.Add("proc_selectall ", OracleDbType.Object);
//cmd.Parameters.Add("ret_selectall ", OracleDbType.Array);
//cmd.Parameters["ret_selectall "].Direction = ParameterDirection.ReturnValue;
//if (connection.State == ConnectionState.Closed)
// connection.Open();
//cmd.ExecuteNonQuery();
Later this...
//OracleCommand objCmd = new OracleCommand("select * from table fsp_SelectAll", connection);
//objCmd.CommandType = CommandType.StoredProcedure;
//objCmd.ExecuteNonQuery();
//int size=objCmd.ExecuteReader().FieldCount;
I also tried with
//adapter = new OracleDataAdapter(cmd);...
But there are always some errors about type, parameters... (Connection to oracle work. I executed Insert, Update, Delete procedures and they work fine)
Also i tried to create this procedure: (this was my first try)
CREATE OR REPLACE PROCEDURE osp_SelectAll (Mjera OUT VARCHAR2,
Status OUT NUMBER, Naziv OUT VARCHAR2,Stat OUT NUMBER) AS
BEGIN
SELECT JEDINICAMJERE.Mjera,
JEDINICAMJERE.Status,
KATEGORIJE.Naziv,
KATEGORIJE.Status as Stat INTO Mjera, Status, Naziv, Stat
FROM JEDINICAMJERE, KATEGORIJE;
END osp_SelectAll;
But it doesn't return any row or rows... and i give up.
Please help me, i need to solve this.
回答1:
Returning a user defined object is not so easy, it requires a lot of additional effort.
Try this one:
create or replace function fsp_SelectAll return SYS_REFCURSOR is
res SYS_REFCURSOR;
BEGIN
OPEN res FOR
SELECT JEDINICAMJERE.Mjera,
JEDINICAMJERE.Status,
KATEGORIJE.Naziv,
KATEGORIJE.Status as Stat
FROM JEDINICAMJERE, KATEGORIJE;
return res;
END;
and then
OracleCommand objCmd = new OracleCommand("fsp_SelectAll", connection);
objCmd.CommandType = CommandType.StoredProcedure;
objCmd.Parameters.Add("res", OracleDbType.RefCursor, ParameterDirection.ReturnValue);
var da = new OracleDataAdapter(objCmd);
var dt = new DataTable();
da.Fill(dt);
Or you can use ExecuteReader()
, if you prefer:
OracleDataReader dr = objCmd.ExecuteReader();
while ( dr.Read() ) {
...
}
dr.Close();
Note, I never worked with .CommandType = CommandType.StoredProcedure;
. If it fails use this syntax:
OracleCommand objCmd = new OracleCommand("BEGIN :res := fsp_SelectAll; END;", connection);
objCmd.CommandType = CommandType.Text;
来源:https://stackoverflow.com/questions/47168430/oracle-function-return-rows-into-c-sharp