Home » SQL & PL/SQL » SQL & PL/SQL » sorting a nested table/collection (Oracle 10g)
sorting a nested table/collection [message #530810] Thu, 10 November 2011 14:23 Go to next message
shijumic
Messages: 31
Registered: May 2010
Member
In test.pks file I declared the following type

TYPE tab_tests is table of NUMBER(15);

In test.pkb, I have the following procedure

PROCEDURE report (
i_cid  IN NUMBER
)
IS
    test1 tab_tests := tab_tests();
    test2 tab_tests;
BEGIN

-- I populate test1 with the data and it works fine

-- But when I tried to make a sorted nested table with the following command 
I got this error 'ORA-00902: invalid datatype', is there any other efficient way to sort 
a nested table than the following, like a built in Oracle collection method?
   execute immediate 'select cast( multiset (select * from table(test1) order by 1) as tab_tests) INTO test2 FROM dual';
END;

[Updated on: Thu, 10 November 2011 14:48] by Moderator

Report message to a moderator

Re: sorting a nested table/collection [message #530811 is a reply to message #530810] Thu, 10 November 2011 14:35 Go to previous messageGo to next message
BlackSwan
Messages: 26766
Registered: January 2009
Location: SoCal
Senior Member
Since I am old an senile, remind me all the advantages that Nested Tables provide over regular Heap Tables.
Re: sorting a nested table/collection [message #530812 is a reply to message #530811] Thu, 10 November 2011 14:46 Go to previous messageGo to next message
shijumic
Messages: 31
Registered: May 2010
Member
I am not a PL/SQL guy, I am using Nested table/collection so that I can store the temporary/staging data in it to create some reports. I was told by Oracle DBA in my company not to use gtt or something in the procedure and I am pretty new to PL/SQL. Is there any way I can sort the data in a nested table and loop through it to do some calculations? some example would be really helpful.

Thanks!
Re: sorting a nested table/collection [message #530814 is a reply to message #530812] Thu, 10 November 2011 14:57 Go to previous messageGo to next message
Michel Cadot
Messages: 68773
Registered: March 2007
Location: Saint-Maur, France, https...
Senior Member
Account Moderator
Quote:
In test.pks file I declared the following type
TYPE tab_tests is table of NUMBER(15);

PL/SQL type are not available in SQL in 10g.

And do NOT use EXECUTE IMMEDIATE for a static SELECT.
in addition, your usage of EXECUTE IMMEDIATE is syntaxically wrong.

Read:
PL/SQL User's Guide and Reference
Application Developer's Guide - Fundamentals

SQL> create type tab_tests is table of NUMBER(15);
  2  /

Type created.

SQL> create or replace PROCEDURE report (
  2  i_cid  IN NUMBER
  3  )
  4  IS
  5      test1 tab_tests := tab_tests();
  6      test2 tab_tests;
  7  BEGIN
  8    select * bulk collect into test2 from table(test1) order by 1;
  9  END;
 10  /

Procedure created.

Regards
Michel
Re: sorting a nested table/collection [message #530817 is a reply to message #530814] Thu, 10 November 2011 15:29 Go to previous messageGo to next message
shijumic
Messages: 31
Registered: May 2010
Member
I tried your approach, but it errored in the following line
select * bulk collect into test2 from table(test1) order by 1;

PL/SQL: ORA-22905: cannot access rows from a non-nested table
item
PLS-00642: local collection types not allowed in SQL statements
Re: sorting a nested table/collection [message #530819 is a reply to message #530817] Thu, 10 November 2011 15:36 Go to previous messageGo to next message
BlackSwan
Messages: 26766
Registered: January 2009
Location: SoCal
Senior Member
It would be helpful if you followed Posting Guidelines - http://www.orafaq.com/forum/t/88153/0/
Re: sorting a nested table/collection [message #530820 is a reply to message #530817] Thu, 10 November 2011 16:14 Go to previous messageGo to next message
Solomon Yakobson
Messages: 3305
Registered: January 2010
Location: Connecticut, USA
Senior Member
shijumic wrote on Thu, 10 November 2011 16:29
I tried your approach


No you did not. Otherwise you would not get "local collection types not allowed in SQL statements" which tells me you still declaring tab_tests in PL/SQL. You need:

a) declare it in SQL like Michel did
b) remove type tab_tests declaration from the package since it takes precedence over SQL declared type. Or prefix type name with type schema name to explicitly tell PL/SQl which tab_tests type you have in mind:

SQL> create type tab_tests is table of NUMBER(15);
  2  /

Type created.

SQL> create or replace package pkg1
  2  as
  3  type tab_tests is table of NUMBER(15);
  4  PROCEDURE report(i_cid  IN NUMBER
  5  );
  6  end;
  7  /

Package created.

SQL> create or replace package body pkg1
  2  as
  3  PROCEDURE report (
  4  i_cid  IN NUMBER
  5  )
  6  IS
  7      test1 tab_tests := tab_tests();
  8      test2 tab_tests;
  9  BEGIN
 10  
 11  select * bulk collect into test2 from table(test1) order by 1;
 12  end;
 13  end;
 14  /

Warning: Package Body created with compilation errors.

SQL> show err
Errors for PACKAGE BODY PKG1:

LINE/COL ERROR
-------- -----------------------------------------------------------------
11/1     PL/SQL: SQL Statement ignored
11/39    PL/SQL: ORA-22905: cannot access rows from a non-nested table
         item

11/45    PLS-00642: local collection types not allowed in SQL statements
SQL> create or replace package body pkg1
  2  as
  3  PROCEDURE report (
  4  i_cid  IN NUMBER
  5  )
  6  IS
  7      test1 scott.tab_tests := scott.tab_tests();
  8      test2 scott.tab_tests;
  9  BEGIN
 10  
 11  select * bulk collect into test2 from table(test1) order by 1;
 12  end;
 13  end;
 14  /

Package body created.

SQL> 


SY.
Re: sorting a nested table/collection [message #530973 is a reply to message #530820] Fri, 11 November 2011 10:54 Go to previous messageGo to next message
shijumic
Messages: 31
Registered: May 2010
Member
I tried it in the way syakobson explained and it worked. Thanks much everyone for the help!
Re: sorting a nested table/collection [message #530975 is a reply to message #530973] Fri, 11 November 2011 11:16 Go to previous messageGo to next message
shijumic
Messages: 31
Registered: May 2010
Member
One more question - How can I get the elements in a collection in the descending order? I tried the following but it didn't work.
 -- I have the data in test2 in a sorted order
 for i in test2.LAST .. test2.FIRST
    LOOP
        DBMS_OUTPUT.PUT_LINE(test2(i));
    END LOOP;
Re: sorting a nested table/collection [message #530976 is a reply to message #530975] Fri, 11 November 2011 11:29 Go to previous messageGo to next message
Michel Cadot
Messages: 68773
Registered: March 2007
Location: Saint-Maur, France, https...
Senior Member
Account Moderator
Just order them in descending order!

Regards
Michel
Re: sorting a nested table/collection [message #531022 is a reply to message #530976] Fri, 11 November 2011 16:12 Go to previous messageGo to next message
Barbara Boehmer
Messages: 9106
Registered: November 2002
Location: California, USA
Senior Member
You can also use REVERSE as shown below.

SCOTT@orcl_11gR2> CREATE OR REPLACE TYPE tab_tests IS TABLE OF NUMBER(15);
  2  /

Type created.

SCOTT@orcl_11gR2> CREATE OR REPLACE PROCEDURE report
  2    (i_cid  IN NUMBER)
  3  IS
  4    test1 tab_tests := tab_tests();
  5    test2 tab_tests;
  6  BEGIN
  7    test1 := tab_tests (1, 3, 4);
  8    SELECT * BULK COLLECT
  9    INTO   test2
 10    FROM   TABLE (test1)
 11    ORDER  BY 1;
 12    DBMS_OUTPUT.PUT_LINE ('ascending');
 13    FOR i IN 1 .. test2.LAST LOOP
 14  	 DBMS_OUTPUT.PUT_LINE (test2 (i));
 15    END LOOP;
 16    DBMS_OUTPUT.PUT_LINE ('----------');
 17    DBMS_OUTPUT.PUT_LINE ('descending');
 18    FOR i IN REVERSE 1 .. test2.LAST LOOP
 19  	 DBMS_OUTPUT.PUT_LINE (test2 (i));
 20    END LOOP;
 21  END report;
 22  /

Procedure created.

SCOTT@orcl_11gR2> SHOW ERRORS
No errors.
SCOTT@orcl_11gR2> EXEC report (0)
ascending
1
3
4
----------
descending
4
3
1

PL/SQL procedure successfully completed.

SCOTT@orcl_11gR2>

Re: sorting a nested table/collection [message #531035 is a reply to message #531022] Sat, 12 November 2011 01:00 Go to previous messageGo to next message
Michel Cadot
Messages: 68773
Registered: March 2007
Location: Saint-Maur, France, https...
Senior Member
Account Moderator
When looping on a collection, it is better to do the following:
i := test.FISRT
LOOP 
  EXIT WHEN i IS NULL;
  <do something>
  i := test.NEXT(i);
END LOOP;

or
i := test.FISRT
WHILE i IS NOT NULL LOOP
  <do something>
  i := test.NEXT(i);
END LOOP;


Regards
Michel

[Updated on: Sat, 12 November 2011 01:01]

Report message to a moderator

Re: sorting a nested table/collection [message #531037 is a reply to message #531035] Sat, 12 November 2011 01:15 Go to previous messageGo to next message
Barbara Boehmer
Messages: 9106
Registered: November 2002
Location: California, USA
Senior Member
Michel Cadot wrote on Fri, 11 November 2011 23:00
When looping on a collection, it is better to do the following:
i := test.FISRT
LOOP 
  EXIT WHEN i IS NULL;
  <do something>
  i := test.NEXT(i);
END LOOP;

or
i := test.FISRT
WHILE i IS NOT NULL LOOP
  <do something>
  i := test.NEXT(i);
END LOOP;


Regards
Michel



Assuming you meant FIRST; instead of FISRT and you declared i as a variable, why do you think either of these is better?
Re: sorting a nested table/collection [message #531039 is a reply to message #531037] Sat, 12 November 2011 01:57 Go to previous messageGo to next message
Michel Cadot
Messages: 68773
Registered: March 2007
Location: Saint-Maur, France, https...
Senior Member
Account Moderator
Quote:
Assuming you meant FIRST; instead of FISRT

Am I? Wink

SQL> DECLARE
  2    t tab_tests := tab_tests();
  3  BEGIN
  4    t.extend (4);
  5    t.delete (1);
  6    t.delete (3);
  7    t(2) := 1;
  8    t(4) := 2;
  9    FOR i in 1..t.LAST LOOP
 10      dbms_output.put_line ('t('||i||'): '||t(i));
 11    END LOOP;
 12  END;
 13  /
DECLARE
*
ERROR at line 1:
ORA-01403: no data found
ORA-06512: at line 10


SQL> DECLARE
  2    i pls_integer;
  3    t tab_tests := tab_tests();
  4  BEGIN
  5    t.extend (4);
  6    t.delete (1);
  7    t.delete (3);
  8    t(2) := 1;
  9    t(4) := 2;
 10    i := t.FIRST;
 11    WHILE i IS NOT NULL LOOP
 12      dbms_output.put_line ('t('||i||'): '||t(i));
 13      i := t.NEXT(i);
 14    END LOOP;
 15  END;
 16  /
t(2): 1
t(4): 2

PL/SQL procedure successfully completed.

Regards
Michel
Re: sorting a nested table/collection [message #531041 is a reply to message #531039] Sat, 12 November 2011 02:08 Go to previous messageGo to next message
Barbara Boehmer
Messages: 9106
Registered: November 2002
Location: California, USA
Senior Member
I see. I forgot about sparse collections.
Re: sorting a nested table/collection [message #531044 is a reply to message #531041] Sat, 12 November 2011 02:44 Go to previous messageGo to next message
Michel Cadot
Messages: 68773
Registered: March 2007
Location: Saint-Maur, France, https...
Senior Member
Account Moderator
And, to answer OP's question, to get it in reverse order, replace FIRST by LAST and NEXT by PRIOR.

SQL> DECLARE
  2    i pls_integer;
  3    t tab_tests := tab_tests();
  4  BEGIN
  5    t.extend (4);
  6    t.delete(1);
  7    t.delete(3);
  8    t(2) := 1;
  9    t(4) := 2;
 10    i := t.LAST;
 11    WHILE i IS NOT NULL LOOP
 12      dbms_output.put_line ('t('||i||'): '||t(i));
 13      i := t.PRIOR(i);
 14    END LOOP;
 15  END;
 16  /
t(4): 2
t(2): 1

PL/SQL procedure successfully completed.


Regards
Michel

Re: sorting a nested table/collection [message #531247 is a reply to message #531044] Mon, 14 November 2011 12:37 Go to previous message
shijumic
Messages: 31
Registered: May 2010
Member
Thanks Everyone!
Previous Topic: Problem with PLSql loop
Next Topic: PLS-00103 on "end-of-file" when closing cursor
Goto Forum:
  


Current Time: Fri Dec 19 23:30:33 CST 2025