How to call a procedure with associative arrays in Oracle from Java - jdbc

I have an stored procedure that looks like this:
TYPE ref_cursor IS REF CURSOR;
TYPE parametro IS RECORD (
nombre VARCHAR2(50), -- I want to remove this value and make it the key of the table instead.
valor VARCHAR2(32000),
tipo VARCHAR2(1),
sentencia VARCHAR2(32000)
);
TYPE parametros IS TABLE OF parametro INDEX BY VARCHAR2(50);
PROCEDURE build_cursor (
params IN parametros
results OUT ref_cursor
);
And from the build_cursor procedure, I want to be able to access to the contents of the table by its key.
parametros('key');
However, I don't know how to build an associative array from Java, I have seen only examples of simple arrays, i.e: TYPE parametros IS TABLE OF parametro;
How can I call the build_cursor procedure from java?
I read this: How to call oracle stored procedure which include user-defined type in java? but I don't know what changes do I have to make to his java example for creating the associative array; Where do I put the Key of the current element?
This is a working test from Oracle.
params('key').nombre := 'key'; -- I want this to be removed because it's the key.
params('key').valor := 'Roger';
params('key').tipo := 'V';
params('key').sentencia := 'Something';
-- Call the procedure
pk_sql_utils.build_cursor(
params => params,
results => :results
);

Only SQL objects can be referenced by jdbc, not PL/SQL objects. Associative arrays are PL/SQL objects, so you won't be able to "see" them from jdbc.
You could use a wrapper PL/SQL function with SQL objects (an associative array is analogous to one nested table of indexes and one nested table of values).
You could also use a temporary table: jdbc batch inserts into the temp table, a wrapper procedure (or PL/SQL block) reads the temp table and calls your procedure.

Related

Returning Multiple Values from Oracle Function over Database Link

I have two oracle databases: A and B.
On database A, I have a function which returns user defined type:
create or replace type my_type as object
( id number,
f2 varchar2(4000),
f3 varchar2(4000),
f4 varchar2(4000)
);
and
CREATE OR REPLACE FUNCTION my_function(p_id NUMBER)
RETURN my_type IS
v_f1 VARCHAR2;
v_f2 VARCHAR2;
v_f3 VARCHAR2;
BEGIN
SELECT a.f1, a.f2, a.f3
INTO v_f1, v_f2, v_f3
FROM my_table a
WHERE a.id= p_id;
RETURN my_type (p_id, v_f1, v_f2, v_f3);
END my_function;
When I call this function from Oracle A it returns
BUT, when I call it from Oracle B it throws ERROR:
ORA-30626: function/procedure parameters of remote object types are not supported
Can you tell me, how to get my SQL query results(f1, f2, f3) from database A to database B.
I don't want to call the query thrice, because of the performance issue.
The only solution I came up was to concatenate these three fields in one value on database A and then substring it on database B, do you have any better idea?
Your object "my_type" should have "SERIALIZE" & "DESRIALIZE" functionality, then you should be able to call your function "my_function()" remotely without an error.
See also this question:
ORA-30626: function/procedure parameters of remote object types are not supported
And the oracle doc:
https://www.oracle.com/java/technologies/jpl2-serial.html

is it possible to pass arrays as parameters in procedures?

i'm trying to pass an array as a parameter in my procedure but i keep getting a command unknown error
code
SET SERVEROUTPUT ON;
TYPE pourcentage_remise IS TABLE OF NUMBER INDEX BY commandeproduit.ref_produit%type;
CREATE OR REPLACE PROCEDURE remise_produit( pourcent IN pourcentage_remise,
ref_comm IN commande.ref_commande%type,
c_ht OUT commandeproduit.prix_ht%type,
c_ttc OUT commandeproduit.prix_ttc%type)
IS
CURSOR p_curs IS
SELECT ref_produit, prix_ttc, prix_ht FROM commandeproduit WHERE concerne = ref_comm ;
ref commandeproduit.ref_produit%type;
ttc commandeproduit.prix_ttc%type;
ht commandeproduit.prix_ht%type;
BEGIN
open p_curs;
LOOP
FETCH p_curs into ref, ttc, ht;
EXIT WHEN p_curs%notfound;
dbms_output.put_line(ref, ' ',ht, ' ', ttc);
IF pourcent(ref) THEN
ttc := ttc - ttc * pourcent(ref);
ht := ht - ttc * pourcent(ref);
INSERT INTO commandeproduit(prix_ht, prix_ttc) VALUES(ht, ttc) WHERE concerne = ref_comm AND ref_produit = ref;
END IF;
dbms_output.put_line(ref, ' ',ht, ' ', ttc);
END LOOP;
close p_curs;
END remise_produit;
/
procedure call
DECLARE
pourcentage pourcentage_remise;
reference commande.ref_commande%type :=1;
BEGIN
pourcentage('A01') :=0.15;
pourcentage('B15') :=0.2;
remise_produit(pourcentage, reference);
END;
/
the table
the error in french which means command unknown
please help
Your syntax error is on the declaration of your type so the rest of your code isn't really needed.
TYPE pourcentage_remise IS TABLE OF NUMBER INDEX BY commandeproduit.ref_produit%type;
Several problems
If you are trying to declare a type in SQL, you'd need to use a CREATE TYPE so you're missing the CREATE.
If you are trying to declare a table type in SQL, you can't use an associative array. You'd realistically want a nested table instead.
If you are trying to declare a PL/SQL type, your statement would need to be in a PL/SQL block. You could declare a package that contains an associative array type.
If you want to declare a nested table type in SQL
CREATE TYPE pourcentage_remise IS TABLE OF NUMBER;
If you want to declare an associative array in a PL/SQL package
CREATE OR REPLACE PACKAGE my_collection_pkg
AS
TYPE pourcentage_remise IS TABLE OF NUMBER INDEX BY commandeproduit.ref_produit%type;
END;
If you want to use a nested table type, that changes how you need to initialize your associative array. It should change how you reference elements of that array, but I'm confused by your code. Your procedure appears to be using a numeric index to access an element of the associative array which doesn't make sense if the associative array uses a string as the index.

create Oracle type of the same structure as an existing Oracle table

I'm trying to save a few Java collections in Oracle PL/SQL stored procedure.
Does anyone know, if there is a way to create Oracle type of the same structure as an existing Oracle table? I would like to avoid creating a lot of CREATE OR REPLACE TYPE t_row AS OBJECT(...); , then CREATE OR REPLACE TYPE t_list AS TABLE OF t_row; for each Java collection.
In other words I would like to create something like:
CREATE OR REPLACE TYPE typename AS TABLE OF schema.existing_table;
I was trying to find some information over the web and it seems like there aren't any similar topics.
Any hint would be very much appreciated.
Does the type need to be a SQL type? If you're OK with a PL/SQL type, you can declare a collection of %ROWTYPE records. Presumably, you'd create the types in one or more packages and then use them wherever appropriate.
create table foo (
col1 number,
col2 number
);
create or replace package my_collections
as
type foo_tbl is table of foo%rowtype;
end;
/
declare
foos my_collections.foo_tbl := new my_collections.foo_tbl();
begin
foos.extend(1);
foos(1).col1 := 1;
foos(1).col2 := 2;
dbms_output.put_line( foos.count );
end;
/

Calling a Procedure in Select Statement

I have a package consists of function and procedures
CREATE OR REPLACE PACKAGE BODY schema.pkg_product as
function xxxxx()
procedure product_get(p_product_id IN Number,
P_direct_balance Out Number,
P_indirect_balance Out Number) IS
v_request CLOB :=<soapenv:Envelope xmnlns:----->
v request_end varchar(100) := <can:----->
BEGIN
Selct statement
END
My question is can we can Call the procedure in the select statement and how can I get the P_direct_balance , P_indirect_balance. if so in the select query coz I want to retrieve that data from the procedure.
It's not possible. You could write a function but you cannot use functions with out parameters in SQL. So you'll have to rewrite your code. For instance create two functions that return p_direct_balance and p_indirect_balance.
If rewriting the procedure to be a function with an out parameter is not possible, I would suggest altering the procedure to write the relevant values to a temporary table and commit. Then use your select statement to retrieve the values from the temp table.

Oracle equivalent of stored procedure that returns an inline table?

Example in T-SQL (SQL Server - taken from here):
CREATE PROC proc_authors
#au_lname VARCHAR(40)
AS
SELECT
au_id, au_fname, au_lname, city, state
FROM authors
WHERE au_lname = #au_lname
go
Is it possible in Oracle to create a stored procedure that returns an inline table (without declaring a type - like the above)? If not, what would be the closest alternative? i.e. declare inline type, then use it. The idea is to minimize number of DB permissions that are granted.
Please include sample code as part of your answer.
Reasoning behind using stored procedure vs function - we have legacy software that can only execute stored procedures, or raw queries. It appears that only stored procedures in there have support for parameterized execution, which is what we are after.
try this with ref cursor
PROCEDURE proc_get_tada(ip_user IN VARCHAR2,
op_error_code OUT NUMBER,
op_cursor OUT SYS_REFCURSOR,) AS
BEGIN
OPEN op_cursor FOR
SELECT * FROM your_table yt where yt.user = ip_user;
EXCEPTION
WHEN OTHERS THEN
op_error_code := -1;
END proc_get_tada;
you will get collection of all data from you table you can iterate in java or calling program.
Maybe you are searching for something like this:
create table author
(
au_id number,
au_name varchar2(100)
);
insert into author (au_id, au_name) values(1, 'ME');
create or replace function getAuthor(auName varchar2)
return author%rowtype
is
retval author%rowtype;
begin
select * into retval from author where au_name=auName;
return retval;
end;
declare
auth author%rowtype;
begin
auth := getAuthor('ME');
dbms_output.put_line(auth.au_id);
end;

Resources