Home » SQL & PL/SQL » SQL & PL/SQL » Viewing Object values in select (11.2.0.1.0)
| Viewing Object values in select [message #636997] |
Thu, 07 May 2015 06:21  |
 |
OraFerro
Messages: 433 Registered: July 2011
|
Senior Member |
|
|
Hi All,
I have a user created type that has two values. I have a function that returns back an object of this type. When I use a select statement to select some values in addition to this function, as per the below example:
CREATE OR REPLACE TYPE AFESD2."AMOUNT2" AS OBJECT
(
"AMT1" NUMBER(15,3),
"AMT2" NUMBER(15,3)
);
CREATE OR REPLACE FUNCTION F_try(Req_No in number, exch_rate_date in char default 'TODAY')
Return Amount2 As
Trans_Amts Amount2;
Amt1 Number;
Amt2 Number;
STAT NUMBER;
begin
SELECT 5,6
INTO AMT1,
AMT2
FROM DUAL;
Trans_Amts := AMOUNT2(AMT1,AMT2);
RETURN (Trans_Amts);
END;
/
select 1, f_try(3) from dual;
I need to know if I can write a select (or any other way) in order to get 1, 5, 6 as three separate columns.
Many Thanks,
Ferro
|
|
|
|
|
|
|
|
|
|
| Re: Viewing Object values in select [message #637001 is a reply to message #637000] |
Thu, 07 May 2015 07:06   |
 |
OraFerro
Messages: 433 Registered: July 2011
|
Senior Member |
|
|
Thanks Michel for the advice, I am sure now, it runs once every time the function is selected.
CREATE OR REPLACE FUNCTION F_try(Req_No in number, exch_rate_date in char default 'TODAY')
Return Amount2 As
Trans_Amts Amount2;
Amt1 Number;
Amt2 Number;
STAT NUMBER;
begin
SELECT 5,6
INTO AMT1,
AMT2
FROM DUAL;
DBMS_OUTPUT.PUT_LINE('One run');
Trans_Amts := AMOUNT2(AMT1,AMT2);
RETURN (Trans_Amts);
END;
select 1, f_try(3).AMT1, F_TRY(3).AMT2, f_try(3).AMT1 from dual;
One run
One run
One run
Quote:
is there a way to split the object values in the select without running the function twice?
Ferro
|
|
|
|
|
|
| Re: Viewing Object values in select [message #637005 is a reply to message #637003] |
Thu, 07 May 2015 07:51   |
John Watson
Messages: 9003 Registered: January 2010 Location: Global Village
|
Senior Member |
|
|
I still get multiple executions, even though I added the DETERMINISTIC keyword:orclz> select t.id,
2 t.val.AMT1,
3 t.val.AMT2
4 from (select 1 id,
5 f_try(3) val
6 from dual) t;
ID VAL.AMT1 VAL.AMT2
---------- ---------- ----------
1 5 6
One run
One run
orclz>
orclz> ed
Wrote file afiedt.buf
1 CREATE OR REPLACE FUNCTION F_try(Req_No in number, exch_rate_date in char default 'TODAY')
2 Return Amount2
3 deterministic
4 As
5 Trans_Amts Amount2;
6 Amt1 Number;
7 Amt2 Number;
8 STAT NUMBER;
9 begin
10 SELECT 5,6
11 INTO AMT1,
12 AMT2
13 FROM DUAL;
14 DBMS_OUTPUT.PUT_LINE('One run');
15 Trans_Amts := AMOUNT2(AMT1,AMT2);
16 RETURN (Trans_Amts);
17* END;
orclz> /
Function created.
|
|
|
|
|
|
| Re: Viewing Object values in select [message #637007 is a reply to message #637006] |
Thu, 07 May 2015 08:01   |
John Watson
Messages: 9003 Registered: January 2010 Location: Global Village
|
Senior Member |
|
|
sussed:orclz>
orclz> select t.id,
2 t.val.AMT1,
3 t.val.AMT2,
4 t.val.AMT1 AMT1_2,
5 t.val.AMT2 AMT2_2
6 from (select 1 id,
7 (select f_try(3) from dual) val
8 from dual) t;
ID VAL.AMT1 VAL.AMT2 AMT1_2 AMT2_2
---------- ---------- ---------- ---------- ----------
1 5 6 5 6
One run
orclz>
|
|
|
|
|
|
|
|
| Re: Viewing Object values in select [message #637014 is a reply to message #637010] |
Thu, 07 May 2015 11:20   |
Solomon Yakobson
Messages: 3312 Registered: January 2010 Location: Connecticut, USA
|
Senior Member |
|
|
I wish it would be that easy. Deterministic will not help here. For some unknown reason function returning an object is called each time you reference it directly or indirectly. The only workaround I found is use nested table:
SQL> CREATE OR REPLACE TYPE AMOUNT2 AS OBJECT
2 (
3 "AMT1" NUMBER(15,3),
4 "AMT2" NUMBER(15,3)
5 )
6 /
Type created.
SQL> CREATE OR REPLACE
2 TYPE AMOUNT2_TBL
3 AS TABLE OF AMOUNT2
4 /
Type created.
SQL> CREATE OR REPLACE FUNCTION F_try(Req_No in number, exch_rate_date in char default 'TODAY')
2 Return Amount2 As
3 Trans_Amts Amount2;
4
5 Amt1 Number;
6 Amt2 Number;
7 STAT NUMBER;
8
9 begin
10
11 SELECT 5,6
12 INTO AMT1,
13 AMT2
14 FROM DUAL;
15 Trans_Amts := AMOUNT2(AMT1,AMT2);
16 DBMS_OUTPUT.PUT_LINE('Fire!');
17 RETURN (Trans_Amts);
18
19 END;
20 /
Function created.
SQL> SELECT 1,
2 p.*
3 FROM TABLE(AMOUNT2_TBL(f_try(3))) p
4 /
1 AMT1 AMT2
---------- ---------- ----------
1 5 6
Fire!
SQL>
SY.
|
|
|
|
| Re: Viewing Object values in select [message #637015 is a reply to message #637014] |
Thu, 07 May 2015 11:27   |
John Watson
Messages: 9003 Registered: January 2010 Location: Global Village
|
Senior Member |
|
|
I think you have hit on the problem, SY - the function returns an object, which has all sorts of restrictions. For example, I tried to sneak up on the problem by adding the RESULT CACHE clause, but that doesn't compile:Errors for FUNCTION F_TRY:
LINE/COL ERROR
-------- -----------------------------------------------------------------
0/0 PL/SQL: Compilation unit analysis terminated
2/9 PLS-00999: implementation restriction (may be temporary)
RESULT_CACHE is disallowed on subprograms with RETURN parameter
of (or containing) object type
orclz> This is in 12.1.0.2.
|
|
|
|
| Re: Viewing Object values in select [message #637114 is a reply to message #637015] |
Mon, 11 May 2015 01:10  |
 |
OraFerro
Messages: 433 Registered: July 2011
|
Senior Member |
|
|
Thanks SY and all,
This solution works perfect and even when I use it in a stored procedure (which is the main purpose) it works just fine. However I have a more general question.
For using the function I need to create a user type (table) in order to use in the the FROM clause and freely choose function object variables in the select. Another approach is to replace the function and its mapping table with a view that produces the table in the from clause.
The only disadvantage that I can see with the view approach is that the view will run on the full table without any filter clause until it is filtered with a where clause when called in the stored procedure.
I appreciate if you can correct me or add any points that can help me decide between the two approaches.
--test table
create table t_try1 (v1 number, v2 number, v3 number);
INSERT ALL
INTO t_try1 VALUES (1, 15, 67)
INTO t_try1 VALUES (2, 16, 3)
INTO t_try1 VALUES (11, 85, 49)
INTO t_try1 VALUES (22, 56, 13)
INTO t_try1 VALUES (13, 25, 7)
INTO t_try1 VALUES (42, 156, 31)
INTO t_try1 VALUES (51, 35, 47)
INTO t_try1 VALUES (2, 656, 43)
INTO t_try1 VALUES (10, 95, 647)
INTO t_try1 VALUES (20, 596, 443)
SELECT * FROM DUAL;
--function approach
CREATE OR REPLACE FUNCTION F_try(Req_No in number, exch_rate_date in char default 'TODAY')
Return Amount2 As
Trans_Amts Amount2;
Amt1 Number;
Amt2 Number;
STAT NUMBER;
begin
SELECT V2 * 6,V1 *8
INTO AMT1,
AMT2
FROM T_TRY1
where V3 = Req_No ; --the where clause
Trans_Amts := AMOUNT2(AMT1,AMT2);
DBMS_OUTPUT.PUT_LINE('Fire!');
RETURN (Trans_Amts);
END;
SELECT 1,
p.*
FROM TABLE(AMOUNT2_TBL(f_try(49))) p;
create or replace procedure p_try
( param1 in number, CUR_REF OUT SYS_REFCURSOR) as
begin
OPEN CUR_REF FOR SELECT 1,
p.amt1 zz, p.*
FROM TABLE (AMOUNT2_TBL(f_try(param1))) p;
END;
--view approach
create or replace view v_try
as
(
SELECT V2 * 6 vv2,V1 *8 vv1, V3
FROM T_TRY1
);
create or replace procedure p_try2
( param1 in number, CUR_REF OUT SYS_REFCURSOR) as
begin
OPEN CUR_REF FOR SELECT 1,
p.vv1 zz, p.vv1, p.vv2
FROM v_try p
where v3 = param1; --where clause
END;
Thanks
Ferro
[Updated on: Mon, 11 May 2015 01:37] Report message to a moderator
|
|
|
|
Goto Forum:
Current Time: Wed Jul 29 23:50:49 CDT 2026
|