I have the following function
which I inputs parameters to pi_re,pi_1_Date,pi_2_Date
return
id,cd, and type
create or replace FUNCTION RPT_GET_INFO
(pi_re in NUMBER,
pi_1_Date in DATE,
pi_2_Date in DATE)
RETURN object_tbl PIPELINED
IS
data row:= row(NULL, NULL,NULL);
BEGIN
for c_rec in
( SELECT distinct(id), cd,type FROM tbl
WHERE type in('1','2','3','4' )
and cd = pi_re
order by type,
CASE
when type = '1'
then cd
when type = '2'
then cd
when type = '3'
then cd
when type = '4'
then cd
else null
end)
loop
data.id := c_rec.id;
data.cd := c_rec.cd;
data.type := c_rec.type;
pipe row(data);
end loop;
END RPT_GET_INFO;
I also have a procedure that I call like this
DECLARE
cur RPT_PKG.curtype;
BEGIN
package_PKG.GET_result_procedure(
10, ---- cd
to_date('31/12/2022', 'dd/mm/rrrr'), --- pi_1_Date
to_date('31/12/2022', 'dd/mm/rrrr'), ----pi_2_Date
'120500', -----id
'3', ---type
cur
);
DBMS_SQL.RETURN_RESULT(cur);
END;
target is when I call the function
to call the package at the same time as the found parameters from the function
the function only uses the parameter pi_re
the result of the function and the dates from the
input parameters of the function are used as input parameters of the package
Related
Here is my function func in my package A:
create or replace PACKAGE A AS
type MY_TYPE IS TABLE OF MYTABLE%ROWTYPE;
FUNCTION func RETURN MY_TYPE;
END A;
create or replace PACKAGE BODY A AS
FUNCTION func RETURN MY_TYPE IS
CURSOR myCursor IS
SELECT * FROM MYTABLE;
var_cursor MYTABLE%ROWTYPE;
myParam MY_TYPE;
i NUMBER := 1;
BEGIN
FOR var_cursor IN myCursor
LOOP
myParam.EXTEND;
myParam(i) := var_cursor;
i := i + 1;
END LOOP;
RETURN myParam;
END func;
END A;
I want to call this function.
DECLARE
type my_type IS TABLE OF MYTABLE%ROWTYPE;
variable my_type;
BEGIN
variable := A.func();
END;
This gives error
PLS-00382: expression is of wrong type
The types are the same, so what am I doing wrong and how can I fix it?
You need to use the same type, not an identical but separately defined type:
DECLARE
variable a.my_type;
BEGIN
variable := A.func();
END;
Your function will not compile. If you use "end " to finish a a function/procedure the so in this case "end func;" Also, you are doing way too much code. No need to LOOP at all, instead use bulk collect.
create or replace package body a as
function func return my_type is
begin
select *
from mytable;
bulk collect into myparam;
return myparam;
end func;
end a
Here is one of oracle functions. There is a cursor called c_adv_course_credit which receives 2 parameters. These 2 parameters are using the where statement:
WHERE
-- year
cc.year = p_year AND
-- rela_pk
cc.sequence_number = p_sequence_number AND
cc.closed_ind = 'N';
When I run it in oracle sql developer:
SET SERVEROUTPUT ON
variable res varchar2(200);
EXECUTE :res := advp_test_cursor(2018, 92919);
select :res from dual;
The result text is always "not working"
Here is the full function (not working):
CREATE OR REPLACE Function SISD_OWNER.advp_test_cursor (
p_sequence_number IN NUMBER, -- rela_pk
p_year IN NUMBER -- year
)
RETURN VARCHAR2
IS
v_return_var VARCHAR2(300) := 'not working';
CURSOR c_adv_course_credit (
p_sequence_number IN NUMBER,
p_year IN NUMBER
)
IS
SELECT
cc.EXTERNAL_COURSE_CD
FROM
adv_course_credit cc
WHERE
cc.year = p_year AND
-- rela_pk
cc.sequence_number = p_sequence_number AND
cc.closed_ind = 'N';
BEGIN
FOR v_at_rec IN c_adv_course_credit(p_sequence_number, p_year) LOOP
v_return_var := v_at_rec.EXTERNAL_COURSE_CD;
DBMS_OUTPUT.PUT_LINE('?output = ' || v_return_var);
EXIT;
END LOOP;
RETURN v_return_var;
END;
If I change the cursor to use hard-coded numbers the function works and returns actual result.
WHERE
-- year
cc.year = 2018 AND
-- rela_pk
cc.sequence_number = 92919 AND
cc.closed_ind = 'N';
Your function is defined as (ignoring the data types):
advp_test_cursor(p_sequence_number, p_year)
but you're calling it as
advp_test_cursor(2018, 92919);
which has the arguments the wrong way round. You either need to flip them:
advp_test_cursor(92919, 2018);
or use named parameter notation:
advp_test_cursor(p_year=>2018, p_sequence_number=>92919)
or indeed combine both:
advp_test_cursor(p_sequence_number=>92919, p_year=>2018)
You do not need to use cursors:
CREATE OR REPLACE Function SISD_OWNER.advp_test_cursor (
p_sequence_number IN adv_course_credit.sequence_number%TYPE,
p_year IN adv_course_credit.year%TYPE
) RETURN adv_course_credit.EXTERNAL_COURSE_CD%TYPE
IS
v_return_var adv_course_credit.EXTERNAL_COURSE_CD%TYPE;
BEGIN
SELECT EXTERNAL_COURSE_CD
INTO v_return_var
FROM adv_course_credit
WHERE year = p_year
AND sequence_number = p_sequence_number
AND closed_ind = 'N';
DBMS_OUTPUT.PUT_LINE('?output = ' || v_return_var);
RETURN v_return_var;
EXCEPTION
WHEN NO_DATA_FOUND THEN
RETURN 'Not working';
END;
I have a function which is having three different queries. First query is returning a single record in a plsql record type.Second query is returning another single value and third is also returning a different single value. Now I want to append first record with those two values and return a table of that new record from my function. How can I achieve that.
create or replace function test(p_actBillDat date) return <what should I return> as
type tab_accountNum is table of account.account_num%type;
var_accountNum tab_accountNum;
type query1Record is record(
accountNum account.account_num%type,
customerRef customer.customer_ref%type,
internalCreditScore CUSTOMERATTRIBUTES.Internal_Credit_Score%type);
var_query1Rec query1Record;
var_nsfDat date;
var_writeOffdat date;
cursor cur_accountNum is
select ACCOUNT_NUM
from BILLSUMMARY
where trunc(ACTUAL_BILL_DTM) = p_actBillDat
and CANCELLATION_REQUEST_DAT is null;
begin
open cur_accountNum;
Loop
fetch cur_accountNum bulk collect
into var_accountNum limit 100;
close cur_accountNum;
for i in 1 .. var_accountNum.count
loop
select A.ACCOUNT_NUM, A.CUSTOMER_REF, CA.INTERNAL_CREDIT_SCORE
into var_query1Rec
from ACCOUNT A, CUSTOMERATTRIBUTES CA, CONTACTDETAILS CD, CONTACT CNT
where A.ACCOUNT_NUM = var_accountNum(i) and
A.CUSTOMER_REF = CA.CUSTOMER_REF(+) and
A.CUSTOMER_REF = CD.CUSTOMER_REF and
CNT.CUSTOMER_REF = A.CUSTOMER_REF and
CD.CONTACT_SEQ = CNT.CONTACT_SEQ and
CD.CONTACT_SEQ = 1 and
CD.START_DAT = (select min(CNTD.START_DAT)
from CONTACTDETAILS CNTD
where CNTD.CONTACT_SEQ = CD.CONTACT_SEQ and
CNTD.CUSTOMER_REF = A.CUSTOMER_REF);
select max(AP.ACCOUNT_PAYMENT_DAT) into var_writeOffdat
from ACCOUNT A, ACCOUNTPAYMENT AP
where A.ACCOUNT_NUM = AP.ACCOUNT_NUM and
A.ACCOUNT_NUM = var_accountNum(i) AND
A.TOTAL_WRITEOFF_TOT <> 0 and
(AP.PAYMENT_ORIGIN_ID = 2 or AP.PAYMENT_ORIGIN_ID = 3) and
AP.CANCELLED_DTM is null and
AP.FAILED_DTM is null;
select max(PP.FAILED_DTM) into var_nsfDat
from ACCOUNTPAYMENT AP, PHYSICALPAYMENT PP
where AP.ACCOUNT_NUM = var_accountNum(i) and
AP.ACCOUNT_PAYMENT_STATUS = 3 and
AP.PHYSICAL_PAYMENT_SEQ = PP.PHYSICAL_PAYMENT_SEQ and
AP.CUSTOMER_REF = PP.CUSTOMER_REF and
PP.PHYSICAL_PAYMENT_STATUS = 3 and
PP.FAILURE_CODE_ID in (select PFC.FAILURE_CODE
from CGPAYMENTFAILURECONFIG PFC
where PFC.FAILURE_TYPE = 'Decline NSF') ;
<how to appned var_query1Rec with var_writeOffdat and var_writeOffdat>
<how to make a PLSQl table of that record and return from function>
end loop;
end loop;
end;
If this function is not part of a package - why wouldn't it be? then you have no other choice but to declare a SQL Object type like this example:
CREATE TYPE person_typ AS OBJECT (
idno NUMBER,
first_name VARCHAR2(20)
);
Declare the variables at the top of your function to access the type created.
type t_arr is table of person_typ ;
l_arr t_arr := t_arr();
Then assign them in your code:
l_arr.extend;
l_arr(i).idno := xxx;
l_arr(i).first_name := yyyy;
The create function returns the object:
create or replace function test(p_actBillDat date) return person_typ as
.....
return(l_arr);
end;
But I would have this function in a package then in the package body header or spec you could do this:
type t_rec is
record(x number
,y varchar2(100)
);
type t_tbl is table of t_rec index by binary_integer;
Then declare in your function:
l_tbl t_tbl;
Then assign them in the function:
l_tbl(i).x := xxx;
l_tbl(i).y := yyy;
And finally just return the type in your function like this:
create or replace function test(p_actBillDat date) return t_tbl as
......
l_tbl t_tbl;
begin
.......
for i in 1..counter loop
.. SQL statements
l_tbl(i).x := xxx;
l_tbl(i).y := yyy;
end loop;
return l_tbl;
end;
I have the following table:
T_TYPE_ID T_TYPE T_TYPE_PRICE T_TYPE_START_DATE T_TYPE_END_DATE
1 student 10.95 01.04.2015 00:00:00 30.06.2015 00:00:00
2 Concession 5.5 01.04.2015 00:00:00 30.06.2015 00:00:00
I need to:
Create FUNC_get_ t_type_end_date function
This function should contain the following input parameter: t_type_p and the following output parameters: t_type_price_p and t_type_end_date_p. It should return 1 if having a record with t_type as t_type_p otherwise return 0. In addition, in the case of having a record, it should assign the latest t_type_end_date to t_type_end_date_p and t_type_price to t_type_price_p. Please note that t_type_end_date_p can be null; it means that the associated price is currently valid.
I have written the following code:
CREATE OR REPLACE FUNCTION FUNC_get_t_type_end_date
( t_type_p IN VARCHAR2)
RETURN NUMBER
AS
cnum NUMBER;
CURSOR cr1 IS
SELECT t_type
FROM ticket_type
WHERE t_type = t_type_p;
BEGIN
OPEN cr1;
FETCH cr1 INTO cnum;
IF cr1%NOTFOUND THEN
cnum := 0;
END IF;
CLOSE cr1;
RETURN cnum;
END;
I did not get any clue on how to return multiple values from a function. I am using oracle.
Hint:
create or replace FUNCTION FUNC_get_ t_type_end_date (…)
return number
as
-- define a variable to return a number and assign 0 to it
-- define a cursor to obtain t_type_price, t_type_end_date of the given t_type_p. The t_type_end_date values should be sorted in descending order – to do so the first record will contain either null or the latest of t_type_end_date
BEGIN
-- open cursor
-- fetch the first record from the cursor to t_type_price_p and t_type_end_date_p
-- if (having a record) then …
-- close cursor
RETURN …
END;
It is not possible to return more than one variable from function. However, it is possible to return a customized variable (i.e. record) type that contains multiple values. To do this, you need first to define type contains the three variables you want to return as follows:
TYPE new_type is record(cnum number, t_type_end_date_p timestamp, t_type_price_p timestamp);
Then you can use it in your function as follows:
CREATE OR REPLACE FUNCTION FUNC_get_t_type_end_date ( t_type_p IN VARCHAR2)
RETURN new_type AS
new_type_variable newtype;
CURSOR cr1 IS
SELECT t_type
FROM ticket_type
WHERE t_type = t_type_p;
BEGIN
OPEN cr1;
FETCH cr1 INTO cnum;
IF cr1%NOTFOUND THEN
SELECT 0, null, null into new_type_variable from dual;
ELSE
SELECT 1, cr1.t_type_end_date, cr1.t_type_price into new_type_variable from dual;
END IF;
CLOSE cr1;
RETURN new_type_variable ;
END;
Try this:
create or replace function func_get_t_type_end_date(t_type_p in varchar2, t_type_price_p out number, t_type_end_date_p out date) return number
as
cnum NUMBER;
CURSOR cr1 IS
SELECT t_type_price,t_type_end_date
FROM ticket_type t
WHERE t_type = t_type_p
and not exists (select 1
from ticket_type t2
where t2.t_type = t.t_type
and t2.t_type_end_date>t.t_type_end_date);
BEGIN
OPEN cr1;
FETCH cr1 INTO t_type_price_p,t_type_end_date_p;
IF cr1%NOTFOUND THEN
cnum := 0;
else
cnum := 1;
END IF;
CLOSE cr1;
RETURN cnum; end;
Example of using:
set serveroutput on
declare
v_result number;
v_type_price_p number;
v_type_end_date_p date;
begin
v_result:=func_get_t_type_end_date(t_type_p=>'student',t_type_price_p=>v_type_price_p,t_type_end_date_p=>v_type_end_date_p);
dbms_output.put_line('Result: '||v_result);
dbms_output.put_line('Price: '||v_type_price_p);
dbms_output.put_line('End date: '||v_type_end_date_p);
end;
/
In Oracle/PLSQL, the greatest function returns the greatest value in a list of expressions. The syntax for greatest function is
greatest( expr1, expr2, ... expr_n )).
How can I write my function with unlimit parameter like this:
myfunction(param1 , param2,...param_n)
You could simulate var args using a table type as the parameter.
create or replace type VARGS as table of varchar2(32767);
You can then use this type as the last parameter of the function:
CREATE OR REPLACE Function FNC_COUNT_WITH_NAMES
( P_NAMES IN VARGS )
RETURN number
IS
RT_COUNT NUMBER;
BEGIN
select count(*) INTO rt_count from employees where name IN
(
select * from TABLE(p_names))
);
return rt_count;
END;
Client code would call it with:
exec FNC_COUNT_WITH_NAMES (vargs('Brian','Mike','John','David', 'Bob'));
or
select FNC_COUNT_WITH_NAMES (vargs('Brian','Mike','John','David', 'Bob')) from dual;