Skip to Main Content
  • Questions
  • How to use member functions and procedures?

Breadcrumb

Question and Answer

Tom Kyte

Thanks for the question, BALA.

Asked: August 19, 2000 - 5:02 am UTC

Last updated: May 05, 2003 - 11:33 am UTC

Version: 8.1.6

Viewed 10K+ times! This question is

You Asked

Dear sir,
Give one small example about member functions and procedures.
How to use,create and execute.

Thanking you sir,
balu

and Tom said...

To create:

tkyte@ORACLE8I> create type foo as object
2 ( x number,
3 y number,
4
5 member function dist_from_orgin return number
6 )
7 /

Type created.

tkyte@ORACLE8I>
tkyte@ORACLE8I> create type body foo
2 as
3 member function dist_from_orgin return number
4 is
5 begin
6 return sqrt( x*x+y*y );
7 end;
8 end;
9 /

Type body created.

To use in PLSQL -- as a way to extend the set of datatypes available in that language:

tkyte@ORACLE8I> declare
2 my_variable foo;
3 begin
4 my_variable := foo( 1, 2 );
5
6 dbms_output.put_line( my_variable.dist_from_orgin() );
7 end;
8 /
2.23606797749978969640917366873127623544

PL/SQL procedure successfully completed.

and as a way to use to extend the set of persistent SQL types:

tkyte@ORACLE8I> create table t ( pt foo );

Table created.

tkyte@ORACLE8I>
tkyte@ORACLE8I>
tkyte@ORACLE8I> insert into t values ( foo(2,5) );

1 row created.

tkyte@ORACLE8I>
tkyte@ORACLE8I> column data format a10
tkyte@ORACLE8I> select t.pt data, t.pt.dist_from_orgin() from t t
2 /

DATA(X, Y) T.PT.DIST_FROM_ORGIN()
---------- ----------------------
FOO(2, 5) 5.38516481

Rating

  (5 ratings)

Is this answer out of date? If it is, please let us know via a Comment

Comments

Returns error

vinci, December 04, 2001 - 12:26 pm UTC

The last statement returns error for me:
Here it is:-

SQL> select t.pt data, t.pt.dist_from_orgin() from t ;
select t.pt data, t.pt.dist_from_orgin() from t
                       *
ERROR at line 1:
ORA-00904: invalid column name

Im running 8.1.7 in windows 2000 

Tom Kyte
December 04, 2001 - 12:53 pm UTC

you didn't type in what I had:

tkyte@ORACLE8I> column data format a10
tkyte@ORACLE8I> select t.pt data, t.pt.dist_from_orgin() from t t
2 /


you need to use a correlation name with objects -- "from t t" -- not "from t"

vinci, December 04, 2001 - 2:16 pm UTC

Thanks tom..it worked.That was fast...u r not overloaded r u??(kidding)
I hav another query:
In the member function if I pass a parameter & write code to check a condition and return 1 or 0, will this be faster than directly retreiving the column? Here is an example-

create type mytype as object
( ind1 varchar2(2),
ind2 varchar2(2)
member function check1(myvar IN number) return number
)

create type body mytype as
member function check1(myvar IN number) return number
is
b varchar2(2);
begin
select t.col1.mytype.ind1 into b from t t where col2 = myvar;
if b='A' then
return 1;
else
return 0;
end if;
end;
end;

create table t ( col1 mytype, col2 number,col3..col4....etc);

insert into t (col1,col2) values (mytype('A','B'),5);
insert into t (col1,col2) values (mytype('A','B'),6);
insert into t (col1,col2) values (mytype('A','C'),7);

Now from the front end(JSP) if link1 is clicked, i pass the value 'myvar' (say 5) to my member function which will query my table and return 1 . If it is 1 i will query the same table to get more columns to be displayed on the screen.If it is 0 i will query with some lesser cols .

Now my question is - If this is possible then,
1. How do i call the member function from the front end (the syntax...)?
2. Will this approach be faster than directly querying the col1.ind1 column. Meaning ..i just say this in the front end-
select t.col1.ind1 into variable from t t where col2 = myvar;
If variable = 'A' then
select col4,col5.....
else
null;
end if;
3.Is there anyother way to do this to reduce query time.
A direct sql statement will be faster than a function /stored proc right?
4.Also how do i estimate the table size if i use abstract datatypes? Is it more or less?
In the above table if i had seperate cols for ind1 and ind2 instead of an object then what wud be the difference in table size?

Tom Kyte
December 05, 2001 - 4:22 pm UTC

you would just get the attribute yourself, your front end should query:

select t.col1.mytype.ind1 from t t where col2 = :myvar;


the reason is twofold:

1) it'll be faster
2) you need an object instance upon which to invoke the method. That means you ALREADY retrieved the object in order to invoke the method! You cannot invoke the method until you have an instance. Its a chicken and egg (your method would not work unless it was a static method in which case it could just as well be a plsql function)

Just use the query.

To reduce runtime use a ref cursor and execute the following block of code:

declare
type rc is ref cursor;
l_data varchar2(25);
l_query long;
begin
select t.col1.ind1 into l_data from t t where col2 = ?;
if ( l_data = 'A' )
then
l_query := 'select .......';
else
l_query := 'select * from dual where 1=0';
end if;
open ? for l_query;
end;

(better yet, make that a stored procedure). Bind and execute that from java and you'll get your result set in one round trip....

If you estimate the tablesize in the same way I do -- you do it the same way as for anything else. I estimate by loading up some percentage (say from 1/10 to 10% depending on the number of estimated rows) of the table with good sample data and using analyze to see how big it is. Then, I multiply. With the 'hidden' columns that come with object types -- this is the only way to go.



A reader, December 04, 2001 - 2:37 pm UTC

Hi Tom

In which circumstance we should use this functinality.
It is looking complacted.

Tom Kyte
December 05, 2001 - 4:24 pm UTC

what part looks complicated? once you get over the syntax (all new syntax looks complicated at first) its very straight forward.

I use objects in my code all of the time. I tend not to use them as a persistent storage mechanism (call me old fashioned).

And what about "setter" in OO : pb when updating obj attr !

Yannick, March 06, 2003 - 3:37 pm UTC

Tom i've got a BIG pb about OO with Oracle :
Check this out with Oracle 9i 9.0.2 :

Create or replace TYPE TYPE_A as object
(
value_ NUMBER,
MEMBER FUNCTION setValue(v_value NUMBER) RETURN TYPE_A
) INSTANTIABLE NOT FINAL;
/

create or replace TYPE BODY TYPE_A IS
member function setValue(v_value NUMBER) RETURN TYPE_A IS
v_inst TYPE_A := SELF;
v_old_inst TYPE_A := SELF;
begin
if v_old_inst.value_ != v_value then
v_inst.value_ := v_value;
dbms_output.put_line('setValue executed');
end if;
return v_inst;
end;

END;
/

create table TEST (ATTR_ TYPE_A);

insert into TEST values(TYPE_A(55));

// This line writes "setValue executed" 3 times, why !!??

update TEST a set ATTR_ = a.ATTR_.setValue(56);

the setValue method will be a great functionnality to keep data coherence, and i would not just use SET ATTR_.value_ = xxx

Any idea please ?

Tom Kyte
March 06, 2003 - 4:08 pm UTC

you realize that'll always rewrite the ENTIRE row and be about the least efficient method to accomplish this seemingly simple task?


Don't assume procedural principles when it comes to relational set operations. I don't know why it calls it three times but -- in the end, it is something upon which you have no control..

is there is diff. between procedure and function

joachim mayer, May 05, 2003 - 11:07 am UTC

hi tom,

thx for the nice example. i was playing around a little bit with your foo type and i ran into a problem i do not understand and i cant find an explantaion ... 

here is my ( your ) example... 

SQL> create type foo as object(
  2     x    number,
  3     y        number,
  4
  5    member function dist_from_orgin return number,
  6
  7    member procedure set_x (  in_x in number ),
  8
  9    member function set_y ( in_y in number ) return number
 10
 11  )
 12  /

Type created.

SQL>
SQL> create type body foo
  2    as
  3      member function dist_from_orgin return number
  4     is
  5     begin
  6         return sqrt( x*x+y*y );
  7     end;
  8
  9     member procedure set_x ( in_x in number )
 10    is
 11    begin
 12         x := in_x;
 13    end;
 14
 15     member function set_y ( in_y in number)
 16     return number
 17     is
 18     begin
 19
 20       y := in_y;
 21
 22       return y;
 23     end;
 24
 25   end;
 26  /

Warning: Type Body created with compilation errors.

SQL> show error
Errors for TYPE BODY FOO:

LINE/COL ERROR
-------- -----------------------------------------------------------------
20/6     PLS-00363: expression 'SELF.Y' cannot be used as an assignment
         target

20/6     PL/SQL: Statement ignored

i added a new function and a procedure to set the x and 
y values... but for some reason i can not assign a value to a attriptute in a function. why does it not work ... and is 
there a work around or do i have to move to procedures using out-parameters. ( i tried this also and it resulted in no error ).
i do not understand the difference behavioure of a member function and a memeber procedure. why is the assigment in
the procedure fine but an error in the function?

thx

joachim "hannibal" mayer 

p.s.: when will your new book come out? 

h. 

Tom Kyte
May 05, 2003 - 11:33 am UTC

to each non-static member procedure/function there is an implicit parameter SELF.  By default for procedures, self it passed IN OUT.  For functions -- only as IN -- this is to maximize your ability to call that function from SQL.  You cannot call a function with out parameters from SQL so we default it to IN.

Here is how to do what you need:

ops$tkyte@ORA920> create type foo as object(
  2     x    number,
  3     y        number,
  4
  5    member function dist_from_orgin return number,
  6
  7    member procedure set_x (  in_x in number ),
  8
  9    member function set_y (<b> SELF in out foo,</b> in_y in number ) return number
 10
 11  )
 12  /

Type created.

ops$tkyte@ORA920>
ops$tkyte@ORA920> create type body foo
  2    as
  3      member function dist_from_orgin return number
  4     is
  5     begin
  6         return sqrt( x*x+y*y );
  7     end;
  8
  9     member procedure set_x ( in_x in number )
 10    is
 11    begin
 12         x := in_x;
 13    end;
 14
 15     member function set_y ( <b>SELF in out foo,</b> in_y in number)
 16     return number
 17     is
 18     begin
 19
 20       y := in_y;
 21
 22       return y;
 23     end;
 24
 25   end;
 26  /

Type body created.


August'ish for the book 

More to Explore

PL/SQL demos

Check out more PL/SQL tutorials on our LiveSQL tool.

PL/SQL docs

PL/SQL reference manual from the Oracle documentation library