Skip to Main Content

Breadcrumb

Question and Answer

Tom Kyte

Thanks for the question, moorthy.

Asked: February 28, 2004 - 3:09 pm UTC

Last updated: April 22, 2006 - 3:21 pm UTC

Version: 8.1.7

Viewed 1000+ times

You Asked

Tom
I have a question regarding Varrays. Why exactly we need them and can you give me an example of its usage.Its good learning from you
Thanks

and Tom said...

I've never used a varray. I used nested table collections in my plsql code.

I never use varray's or nested tables as a persistent storage mechanism (on disk). Only nested tables in my code (as an array type). Varrays are limiting in that you have to define the max upper bound -- nested tables you do not, so I do not use varrays in my code.


see
</code> http://asktom.oracle.com/pls/asktom/f?p=100:11:::::P11_QUESTION_ID:1116249548781 <code>



Rating

  (11 ratings)

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

Comments

But..

dwl, March 01, 2004 - 7:14 am UTC

am i correct in saying though, that if you are passing data from jdbc to oracle and you need to pass arrays or elements or records then a varray of objects is the only way to do it?
This would be a good use of varrays over other types.
plsql tables and nested tables do not work in this case.

Please correct me if this is not true though!



Tom Kyte
March 01, 2004 - 8:38 am UTC

nested tables certainly work -- just as varrays do (in fact the code is the same).


I actually prefer to use global temporary tables when passing "arrays of records" from 3gl to PLSQL. Infinitely easier (to me)

How?

Esther, March 01, 2004 - 9:22 am UTC

Dear Tom,
How would you do that?I mean passing rows of global temp table to procedure or function anything like that.Would you
use REF CURSOR for that?Please show the p-code.
Bye!


Tom Kyte
March 01, 2004 - 10:08 am UTC

I would have java array insert scalars into a gtt and then call a procedure, the procedure would read the gtt with bulk collect if it wanted to process as an array or just read the gtt row by row to process.

Why not VARRAYS for persistent storage?

Matt, March 01, 2004 - 5:09 pm UTC

There is a paper going around our office which suggests that using varrays to store arrays of integer values in a DB (think along the lines of lots of days of meter readings - a reading every 5 minutes) would be more efficient than using NUMBERs.

The argument centralises around the disk space saving of using these types.

My opinion is that we would lose soo much more than we gain (developer time, concurrency, speed). Plus we could gain the space benefits by defining appropriate tables (with NUMBERS) and compressing these (gaining the compression on the primary key).

What are your thoughts?

Why do you not use VARRAYS for persistent storage?


Tom Kyte
March 01, 2004 - 5:23 pm UTC

tell me how you would be USING those numbers. You'll not be using them very nicely in SQL anymore in a varray.

and don't forget, a varray will quickly become a blob stored out of line (over 4,000 bytes -> out of line) meaning it is stored in chunks (4001 bytes will take AT LEAST a chunk of space which is AT LEAST a block of space) and will need to be accessed via a LOB INDEX.

hows about an IOT with primary key = parent_id+timestamp -> data. using index key compression (parent_id stored once)

data is stored ordered.

data is fully "sql friendly"

no extra index structures lying about...


(if you want to know why i do not use them for persistent storage, i wrote about that in expert one on one Oracle -- in the chapter on object types.).

Thanks!

Matt, March 01, 2004 - 6:28 pm UTC

I agree with you wholeheartedly, especially about the SQL friendly comment

An IOT (your suggestion) can even be nicely partitioned!

I have the book, but I still haven't read it cover to cover ...it gets used as more of a reference (by both me and the projects I work on).


Are sql inserts (not direct path) compressible in IOT

Rob, March 01, 2004 - 8:41 pm UTC

Tom:

Does key compression in an IOT work the same as compression in an index i.e. all entries remain compressed even if not inserted via direct path. In a heap table rows are only compressed if inserted in direct path mode or CTAS.



Tom Kyte
March 02, 2004 - 7:20 am UTC

correct, index key compression works all of the time. segment (block level) compression only works on direct path operations (load, appends, alter moves)

OK

Norman, April 21, 2004 - 2:09 pm UTC

Hello Tom,
Regarding varrays,What can be the fastest way to remove the
contents of a varray that is the part of the normal relational table?For example
SQL> create type skills_va as varray(5) of varchar(30);
SQL> create table empl(ename varchar(30),skills skills_va);

I would like to delete the contents of a varray that belongs to a single row?
Any help you can provide?

 

Tom Kyte
April 21, 2004 - 9:03 pm UTC

update empl set skills=null where....




OK

Raju, August 17, 2004 - 9:48 am UTC

Dear Tom,
Could you please show some updates or deletes for Varray
enclosing an object type?
I have given some sample types used by me.
Please do reply.

SQL> create or replace type subj_ty as object(
  2* sub_name varchar2(30),Grade char(1))

Type created.


SQL> create or replace type subj_va as varray(5) of subj_ty
  2  /

Type created.


SQL> create table students(sname varchar2(30),sinfo subj_va);

Table created.

SQL> insert into students values('Joe',subj_va(subj_ty('English','A'),subj_ty('Economics','B'),
  2                               subj_ty('Maths','C'),subj_ty('Science','A'),
  3                               subj_ty('History','B')));

1 row created.

SQL> insert into students values('James',subj_va(subj_ty('English','B'),subj_ty('Economics','A'),
  2                               subj_ty('Maths','B'),subj_ty('Science','A'),
  3*                              subj_ty('History','D')))

1 row created.

SQL> commit;

Commit complete.

I would like to change the contents of Varray.Any methods 
you may provide?

 

Tom Kyte
August 17, 2004 - 10:16 am UTC

first, I'll just state " i would never use a varray or nested table for persistant storage"

especially for this model!!! answer me this batman -- how many students got a B or above in math OR an A in science. sure, you can do it, now, do it efficiently for 40,000 students. the relational model rocks and rolls for its infinitely flexibility. Objects give you tunnel vision -- one myoptic view. Use OR views if you like, but try to avoid these constructs outside of plsql - they do not lend themselves to real world problems.

</code> http://docs.oracle.com/docs/cd/B10501_01/appdev.920/a96594/adobjbas.htm#463813 <code>

<quote>
Oracle does not support piecewise updates on VARRAY columns. However, VARRAY columns can be inserted into or updated as an atomic unit.
</quote>

meaning, you basically have to read the existing varray out -- modify it -- and put it back.



varray

A reader, November 23, 2004 - 5:42 pm UTC

Hi Tom

Please consider the example below.

Item Code: Item1
Item Desc: Item Name

Parameter Val1 Val2 Val3 Val4 Val5

Param1 1 2 3 4 5
Param2 1 2 3 4 5
Param3 1 2 3 4 5

For each item there is an array of parameters and for each parameter there is an array of values. The user should have an ability to insert and update records. I was planning to use VARRAY/NESTED TABLE to implement this design. I agree with you in that if I use these features it will be very difficult to manipulate data. If I choose the relational method I will have to store item details i.e Parameter and its values in a seperate table. So the records in the detail table will look like:

Item1 param1 1
Item1 param1 2
Item1 param1 3
Item1 param1 4
Item1 param1 5

and so on....

Can you think of a better way of doing this?

Please advise.

Tom Kyte
November 23, 2004 - 7:53 pm UTC

well, using a nested table -- you get, well, a relational set of tables with lots of extra "stuff" (extra primary keys, extra foreign keys). so, if you are thinking "nested table" -- stop, just do it the "old fashioned way" (eg: do it using tables with primary and forieng keys)

and if you say "well, i'll just use a varray" -- then I'd say "varrays have fixed sized dimensions, looks like the values for parameter 1 could just be columns...

ok

James, April 22, 2006 - 12:13 pm UTC

Hi Tom,
How to update the varray stored as a database table column?
I tried various ways but nothing seem to work.

SQL> create or replace type nums_va as varying array(10) of number
  2  /

Type created.


SQL> create table t(x varchar2(20),y nums_va)
  2  /

Table created.

SQL> insert into t values('First rec',nums_va(1,2,3,4))
  2  /

1 row created.

SQL> insert into t values('Second rec',nums_va(11,12,13,14))
  2  /

1 row created.

SQL> commit
  2  /

Commit complete.

SQL> update TABLE(select y from t)
  2  .
SQL> 
SQL> 
SQL> update TABLE(select y from t where x = 'First rec')
  2  set column_value = column_value+30
  3  /
set column_value = column_value+30
    *
ERROR at line 2:
ORA-25015: cannot perform DML on this nested table view column


SQL> ed
Wrote file afiedt.buf

  1  update TABLE(select y from t where x = 'First rec')
  2* set column_value = 31 where column_value = 1
SQL> /
set column_value = 31 where column_value = 1
    *
ERROR at line 2:
ORA-25015: cannot perform DML on this nested table view column



SQL> ed
Wrote file afiedt.buf

  1  update TABLE(select y from t where x = 'First rec')p
  2* set p.y = 51 where p.y = 1
SQL> /
set p.y = 51 where p.y = 1
                   *
ERROR at line 2:
ORA-00904: "P"."Y": invalid identifier


How to do the update?? 

Tom Kyte
April 22, 2006 - 3:21 pm UTC

you update the varray - not the components thereof

you

a) read out varray
b) set it to whatever you want
c) update the varray back

Zlatko Sirotic, May 03, 2006 - 2:20 am UTC

SQL> select * from t
  2  /

X
--------------------
Y
--------------------------
First rec
NUMS_VA(1, 2, 3, 4)

Second rec
NUMS_VA(11, 12, 13, 14)



SQL> UPDATE t
  2     SET y = CAST (MULTISET (SELECT COLUMN_VALUE + 30
  3                               FROM TABLE (SELECT y FROM t WHERE x = 'First rec')
  4                            )
  5                   AS nums_va
  6                  )
  7   WHERE x = 'First rec'
  8  /

1 row updated.


SQL> 
SQL> select * from t
  2  /

X
--------------------
Y
-------------------------------------------------------------------------------------
First rec
NUMS_VA(31, 32, 33, 34)

Second rec
NUMS_VA(11, 12, 13, 14)


SQL> rollback
  2  /

Rollback complete.


SQL> UPDATE t
  2     SET y = CAST (MULTISET (SELECT DECODE (ROWNUM, 2, COLUMN_VALUE + 30, COLUMN_VALUE)
  3                               FROM TABLE (SELECT y FROM t WHERE x = 'First rec')
  4                            )
  5                   AS nums_va
  6                  )
  7   WHERE x = 'First rec'
  8  /

1 row updated.


SQL> select * from t
  2  /

X
--------------------
Y
-------------------------------------------------------------------------------------------
First rec
NUMS_VA(1, 32, 3, 4)

Second rec
NUMS_VA(11, 12, 13, 14)


SQL> rollback
  2  /

Rollback complete.



SQL> UPDATE t
  2     SET y = CAST (MULTISET (SELECT DECODE (COLUMN_VALUE, 3, COLUMN_VALUE + 30, COLUMN_VALUE)
  3                               FROM TABLE (SELECT y FROM t WHERE x = 'First rec')
  4                            )
  5                   AS nums_va
  6                  )
  7   WHERE x = 'First rec'
  8  /

1 row updated.

SQL> select * from t
  2  /

X
--------------------
Y
-------------------------------------------------------------------------------------------------
First rec
NUMS_VA(1, 2, 33, 4)

Second rec
NUMS_VA(11, 12, 13, 14)


SQL> rollback
  2  /

Rollback complete.



Best regards 

Varrays & Nested table

Sandeep, June 21, 2007 - 1:17 pm UTC

Hello Sir,

Could you please tell us why do we have to use the EXTEND function for Nested tables and Varrays.
Is it because the internal implementation of these is using Linked List. Thus when we say extend
it does a malloc or calloc (to allocate the memory). If it is so does it mean memory allocation
happens at runtime for them. The EXTEND is not applicable for Index by tables does that mean that
memory is allocated at compile time for it.

Regards
Sandeep