Does it mean anything?
Kamal Kishore, June 14, 2003 - 1:37 pm UTC
Hi Tom,
I have heard this argument:
"It is better to define your own table types in PL/SQL package than to use those defined in DBMS_SQL package, because if you use types defined in DBMS_SQL pacakge, this pacakge will also be loaded in memory (even if you are not going to use its procedures) along with your own package. This would cause your application to require more memory than may be necessary. So, to make less memory footprint and an efficient program, declare your own types and DO NOT use DBMS_SQL table types."
Should we be concerned?
Using DBMS_SQL types instead of defining our own within the package will have a negative effect on performance? Is this true?
Thanks,
June 14, 2003 - 2:18 pm UTC
I have yet to see a database that doesn't use dbms_sql, so it is probably a moot point. dbms_sql is used under the covers by so many things. It is a micro-optimization at best.
Truth be told, you would probably be best off with your own types though, but not for those reasons.
Oracle owns DBMS_SQL. We can change those types any time we want to.
You would own "Kamals_Types_Pkg", you would change them only when you want to.
thanx for the answer to the original question!
A reader, June 14, 2003 - 5:17 pm UTC
Pitty that there is no namespace for SQL types
A reader, June 19, 2003 - 4:06 pm UTC
PLSQL types are neat because they are encapsulated (package name acts like object type name or namespace).
SQL types do not have namespaces and if one would like to use them in real application one would end up complete mess with hundreds of types.
June 20, 2003 - 3:58 pm UTC
why would you have hundreds of types?
Why I have hundreds of types
A reader, June 25, 2003 - 5:27 am UTC
I put all my SQL into procedures and client side just calls these procuderes to select, update, insert or delete.
Typical "select" would be packaged procedure with typed ref cursor. These packages form interface layer between database (PLSQL) and client programm (c/s or web based client). There interface procedures are built from viewpoint of GUI (this is not typical object oriented interface used in 3-tier model).
Simplified example of SELECT and UPDATE procedure:
create or replace package ONE_INTERFACE_PACKAGE is
type TPersonNameRec is record
( ID number(10,0) -- person ID
, NAME varchar2(50) -- person full name to display
);
type TPersonNameCur is ref cursor return TPersonNameRec;
procedure FIND_PERSON
( sNameToSearch IN varchar2
, curOut out TPersonNameCur
);
procedure UPDATE_PERSON
( iID in number(10,0) -- person ID
, sName in varchar2(50) -- person full name to update
);
end ONE_INTERFACE_PACKAGE;
/
create or replace package body ONE_INTERFACE_PACKAGE is
procedure FIND_PERSON
( sNameToSearch IN varchar2
, curOut out TPersonNameCur
) is
begin
open curOut for
select ID, NAME
from PERSONS
where NAME like sNameToSearch;
end;
procedure UPDATE_PERSON
( iID in number(10,0) -- person ID
, sName in varchar2(50) -- person full name to update
) is
begin
update PERSONS
set NAME = sName
where ID = iID;
end;
end ONE_INTERFACE_PACKAGE;
/
So... for each SELECT statement I would have one PLSQL record and one typed cursor. And few hundred types collect up very rapidly.
I would like to use SQL type - because it would be supported by application client side (by client I mean Java, Delphi, PHP etc):
* same type in database and client;
* nested tables could be useful;
* I could use same type in insert/update procedures;
* I could use array types more easily.
Some of this could be implemented with PL/SQL types also but it would be messy at client side. SQL types would make this much easier. But I have no means to partition SQL types at database side.
June 25, 2003 - 12:05 pm UTC
I don't get why you would create a type for a select still.
just return ref cursors -- no types? not getting it.
those clients do not actually SUPPORT types very well. ref cursors -- sure, object types -- not.
so, still not getting it I guess.
Need your help
Devan, March 04, 2004 - 12:51 am UTC
Hi Tom,
In the create type body statement,I came across the clause
"return self as result is pl/sql block or call spec"?How to
use this clause?Does 'self' keyword point to the attributes
defined with in the type declaration?If you have any simple
example, please do write a followup.
Thanks in advance.
March 04, 2004 - 11:01 am UTC
It provides a method to create your own constructor, your own procedural logic to setup the object type:
ops$tkyte@ORA9IR2> create or replace type myType
2 as object
3 ( x int,
4 y date,
5 z varchar2 (25),
6 constructor function myType return self as result,
7 constructor function myType( some_number in number ) return self as result
8 )
9 /
Type created.
ops$tkyte@ORA9IR2>
ops$tkyte@ORA9IR2> create or replace type body myType
2 as
3
4 constructor function myType return self as result
5 is
6 begin
7 x := 55;
8 y := sysdate;
9 z := 'Hello World';
10 return;
11 end;
12
13 constructor function myType( some_number in number ) return self as result
14 is
15 begin
16 x := some_number;
17 y := sysdate+some_number;
18 z := 'Hello World ' || some_number;
19 return;
20 end;
21
22 end;
23 /
Type body created.
ops$tkyte@ORA9IR2>
ops$tkyte@ORA9IR2>
ops$tkyte@ORA9IR2>
ops$tkyte@ORA9IR2> declare
2 x myType := myType();
3 y myType := myType(2);
4 begin
5 dbms_output.put_line( x.x || ', ' || x.y || ', ' || x.z );
6 dbms_output.put_line( y.x || ', ' || y.y || ', ' || y.z );
7 end;
8 /
55, 04-MAR-04, Hello World
2, 06-MAR-04, Hello World 2
PL/SQL procedure successfully completed.
Nice as usual
Jim, March 05, 2004 - 1:32 am UTC
Dear Tom,
In creating types we find "map or order member function"
What is the diff. between "map or order keywords"?.
Please do reply.
Bye!
March 05, 2004 - 7:59 am UTC
Nice
Ram, March 08, 2004 - 10:21 am UTC
Dear Sir,
Please have a look at the following objects.
sql>create type address_ty as object(door_no number,streetname varchar2(30),city varchar2(30));
Now if we create a table as
create table customer(
custname varchar2(30),
address address_ty);
or
create table customer(
custname varchar2(30),
address REF address_ty);
Are both statements equivalent?
What role can REF play in the 2nd statement?what is the
difference between two statements?
Please do reply.
March 08, 2004 - 1:56 pm UTC
no, they are not remotely similar. the first creates a table capable of holding a custname and an address (the data of an address). the second can store a custname and a POINTER to an address object stored in some other table.
the REF is like a pointer - it points to an object instance, typically an instance in another table.
it is "like" a foreing key, only not as good (no RI)
NN
A reader, April 14, 2005 - 1:38 pm UTC
Hi Tom,
I have these external types:
create or replace TYPE cas_to_ec_crdt_app_addr IS RECORD (
qualifier VARCHAR2(40),
addr_line_1 VARCHAR2(40),
addr_line_2 VARCHAR2(40),
city_name VARCHAR2(30),
state_code VARCHAR2(2),
zip_code VARCHAR2(9),
cnty_name VARCHAR2(10)
);
create or replace TYPE cas_to_ec_crdt_app_addr_typ IS TABLE OF cas_to_ec_crdt_app_addr;
create or replace TYPE cas_to_ec_aplcnt_rec IS RECORD (
prim_aplcnt_ind CHAR(1),
aplcnt_frst_name VARCHAR2(15),
aplcnt_mid_name VARCHAR2(15),
aplcnt_last_name VARCHAR2(35),
name_sfx_code VARCHAR2(10),
aplcnt_brth_date DATE,
address_table
cas_to_ec_crdt_app_addr_typ);
create or replace TYPE cas_to_ec_aplcnt_tab IS TABLE OF cas_to_ec_aplcnt_rec;
create or replace TYPE cas_to_ec_vehicle IS RECORD(
vhcl_mdl_year NUMBER(4),
vhcl_make_name VARCHAR2(70),
vhcl_mdl_name VARCHAR2(70),
trad_in_ind CHAR(1)
);
create or replace TYPE cas_to_ec_vehicle_typ IS TABLE OF cas_to_ec_vehicle;
create or replace TYPE copy_ca is record (
crdt_aplcn_oid NUMBER(20),
crdt_aplcn_type_code VARCHAR2(10),
vin VARCHAR2(25),
cas_veh_tab cas_to_ec_vehicle_typ,
trad_in_owed_amt NUMBER(16,2),
trad_alow_on_trad_in_amt NUMBER(16,2),
cash_down_pymt_amt NUMBER(16,2),
mfr_rbt_amt NUMBER(16,2),
vhcl_mdl_year NUMBER(4),
vhcl_make_name VARCHAR2(70),
vhcl_mdl_name VARCHAR2(70),
vhcl_sty_name VARCHAR2(70),
fnc_src_oid NUMBER(20),
rte_one_fnc_src_id VARCHAR2(20),
fnc_src_dba_name VARCHAR2(70),
fnc_term_qty NUMBER(10),
applcnt_table
cas_to_ec_aplcnt_tab
);
And in my package, i am declaring a function which uses that record type:
FUNCTION copy_ca_ssp(
i_crdt_aplcn_oid IN NUMBER,
o_error_cd OUT PLS_INTEGER,
o_error_desc OUT VARCHAR2 ,
o_error_msg OUT VARCHAR2 ,
o_error_type OUT VARCHAR2
) RETURN copy_ca;
When I compile my code; I am getting this error:
PLS-00905: object R1OWNER.COPY_CA is invalid
Could you please guide me?
April 14, 2005 - 1:41 pm UTC
ops$tkyte@ORA9IR2> create or replace TYPE copy_ca is record ( x number )
2 /
Warning: Type created with compilation errors.
because "is record" is "not valid"
create or replace type copy_ca as OBJECT (...... ) would be
record is PLSQL specific
A reader, April 14, 2005 - 1:47 pm UTC
Thanks Tom,
I did what you suggested:
create or replace TYPE copy_ca as object(x nnumber).
I am still get the same error.
Can I use types in an object?
I mean can be a record type in the above statement?
Thanks in advance!
April 14, 2005 - 1:59 pm UTC
records only work in PLSQL, not in create or replace type's.
A reader, April 14, 2005 - 1:50 pm UTC
can X be a record type in above statement?
April 14, 2005 - 1:59 pm UTC
yes, but the record type would be defined in the scope of PLSQL, not SQL.
that is, it would be a type inside of a package specificiation.
A reader, April 14, 2005 - 2:12 pm UTC
Thanks a lot Tom!
I have another issue:
Here are the details:
type A as object(
c1 number;
my_B type1
);
type type1 is table of B;
type B is object(
c2 number,
c3 varchar2,
my_C type2
);
type type2 is table of C;
type C is object(
c4 date
);
-------------
In my procedure I am giving following statement:
my_A A;
select data1,data2,..
bulk collect into my_A.my_B.my_C
from table1
where <conditions>
And I am getting following error:
PLS-00302: component 'my_C' must be declared
Could you please help me!
April 14, 2005 - 2:16 pm UTC
small, concise, yet 100% complete.... and in the order needed to execute.
make it as short as possible, yet runnable by anyone on the planet and I'll have a look. use scott/tiger tables for example
A reader, April 14, 2005 - 2:27 pm UTC
Sorry about that! Hope the following is clear, I have nested types, so cannot simplify the type structure:
I have declared following types at schema level:
create or replace type C is object(
start_date date,
end_date date
);
create or replace type table2 is table of C;
create or replace type B is object(
c2 number,
c3 varchar2,
my_C table2
);
create or replace type table1 is table of B;
create or replace type A as object(
c1 number;
my_B table1
);
----
In my procedure I am giving following statement:
procedure p1
is
my_A A;
begin
select sysdate,hiredate
bulk collect into my_A.my_B.my_C
from emp;
end;
And I am getting following error:
PLS-00302: component 'my_C' must be declared
Thanks a lot!
April 14, 2005 - 2:47 pm UTC
(always nice to have a script that runs! varchar2, does not compile... c1 number; does not compile.....)
anyway
my_a is a scalar object.
my_a.my_b is a TABLE (collection). A.my_b(1).my_c would be valid. A.my_b.my_c is not. you are missing a subscript (and some initialization)
after fixing up script....
ops$tkyte@ORA9IR2> declare
2 my_A A;
3 begin
4
5 my_a := a( null, table1( b(null,null, null ) ) );
6
7 select c(sysdate,hiredate)
8 bulk collect into my_A.my_B(1).my_C
9 from emp;
10 end;
11 /
PL/SQL procedure successfully completed.
A reader, April 14, 2005 - 2:57 pm UTC
Once again thanks a lot.
But, I am still getting the following error:
PL/SQL: ORA-00947: not enough values
I am selecting data for all the columns, what could be the issue?
A reader, April 14, 2005 - 3:00 pm UTC
Can I use Bulk into with objects?
April 14, 2005 - 3:08 pm UTC
yes
A reader, April 14, 2005 - 3:06 pm UTC
Here is what I am trying to do:
declare
my_A A;
begin
my_a := a( null, table1( b(null,null, null ) ) );
select c(ename,sal)
bulk collect into my_A.my_B
from emp;
end;
What is the mistake?
April 14, 2005 - 3:11 pm UTC
ops$tkyte@ORA9IR2> set describe depth all
ops$tkyte@ORA9IR2> desc a
Name Null? Type
---------------------------------------- -------- ----------------------------
C1 NUMBER
MY_B TABLE1
C2 NUMBER
C3 VARCHAR2(25)
MY_C TABLE2
START_DATE DATE
END_DATE DATE
my_a.my_b is a table of three thnigs. You select 1 thing.
Not really sure what your ultimate goal here is, but the shape of what you are trying to select comes no where near the shape of the thing you are selecting INTO.
A reader, April 14, 2005 - 3:20 pm UTC
Very useful information!
I want to bulk collect My_B (including My_C).
How can I do it?
There can be multiple rows in My_B and My_C.
Thanks in advance!
April 14, 2005 - 3:38 pm UTC
well, you sort of would need a result set that fits into it?
You seem to be going backwards in this respect. Normally, you know what you are retrieving and you build a data structure to hold it, here we seem to have a data structure that you want to fill with data?
seems backwards no?
A reader, April 14, 2005 - 3:36 pm UTC
Please help me, it is very urgent!
April 14, 2005 - 3:39 pm UTC
see above, it really does seem backwards. you need simply to select out data that fits the data structure YOU invented?
difference between sql type and plsql type
Magesh, January 06, 2006 - 11:32 am UTC
Tom,
I was trying to get the hang of CAST and hit upon this. Can you please explain what is happening here? When I declare the type in SQL everything works fine but when I try to declare the same as a plsql type, it doesn't seem to work. I understand when I declare the type in plsql, it becomes local to the block and SQL wouldn't recognize it outside the scope of it but I am using the Select .. into inside the plsql block.
SQL> create or replace type num_tab as table of number(10);
2 /
Type created.
SQL> declare
2 --type num_tab is table of number;
3 v_num_tab num_tab;
4 a number;
5 begin
6 v_num_tab := num_tab(10,20,30,40,50);
7 dbms_output.put_line('The numbers are: ');
8 /*for a in (select column_value nums from table(cast(v_num_tab as num_tab))) loop
9 dbms_output.put_line(a.nums);
10 end loop;*/
11 select sum(column_value) into a from table(cast(v_num_tab as num_tab));
12 dbms_output.put_line(a);
13 end;
14 /
The numbers are:
150
PL/SQL procedure successfully completed.
SQL> drop type num_tab;
Type dropped.
SQL> declare
2 type num_tab is table of number;
3 v_num_tab num_tab;
4 a number;
5 begin
6 v_num_tab := num_tab(10,20,30,40,50);
7 dbms_output.put_line('The numbers are: ');
8 /*for a in (select column_value nums from table(cast(v_num_tab as num_tab))) loop
9 dbms_output.put_line(a.nums);
10 end loop;*/
11 select sum(column_value) into a from table(cast(v_num_tab as num_tab));
12 dbms_output.put_line(a);
13 end;
14 /
select sum(column_value) into a from table(cast(v_num_tab as num_tab));
*
ERROR at line 11:
ORA-06550: line 11, column 62:
PL/SQL: ORA-00902: invalid datatype
ORA-06550: line 11, column 1:
PL/SQL: SQL Statement ignored
January 06, 2006 - 2:22 pm UTC
because CAST is a sql function, CAST sees only things "sql", CAST called from SQL like that doesn't see "num_tab" when "num_tab" is a private PLSQL type.
to use a type in SQL, you use SQL to create the type. In general, plsql types are NOT visible outside of PLSQL