Tuesday, 17 January 2012

Oracle Collections in SQL Part1

Well, We have heard a lot about advanced PL/SQL and particularly about Collection(s) of Oracle. Collection(s) comprise Nested Table, Varray and Index By Tables. Each has its own way of working. Most of time, these Collections are used in PL/SQL program. Eg Function, Procedure, Package.
It is not very often when we see any developer using these collections in SQL statement.  Main reason could be because they themselves have not seen actually someone using it. Using Collections in SQL statements add a little more complexity in statement structure so many developer(s) try to skip this and use their old and proven methodology.

In this post , we will discuss exact method to use Nested Table in SQL statement and performance impact on queries using such tables. In first part of this post we will discuss actual working of this and in second post we will discuss performance impact.

Not all three collections could be used in SQL. We can use only Nested Table and Varray in SQL statement.  For to be used in SQL statement these Collection / Types should be stored as an object in Database.




SQL> select banner from v$version;


BANNER
----------------------------------------------------------------
Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - Prod
PL/SQL Release 10.2.0.1.0 - Production
CORE    10.2.0.1.0      Production
TNS for 32-bit Windows: Version 10.2.0.1.0 - Production
NLSRTL Version 10.2.0.1.0 - Production


Step:- 1
Define a Object type and Map method. Following, I have created a type of Object Kind and defined a MAP method for comparison purpose.

SQL> CREATE TYPE SCOTT.COURSE_OBJ AS OBJECT
  2  (
  3  STU_ID NUMBER,
  4  COURSE_ID NUMBER,
  5  COURSE_NAME VARCHAR2(40),
  6  MAP MEMBER FUNCTION MAP1 RETURN NUMBER);
  7  /

1  CREATE TYPE BODY SCOTT.COURSE_OBJ AS
 2  MAP MEMBER FUNCTION MAP1 RETURN NUMBER IS
 3  BEGIN
 4  RETURN STU_ID||COURSE_ID;
 5  END MAP1;
 6* END;

Step 2:- Created a TYPE of Nested Table type and used Course_Obj Object Type that we created in Step 1.


SQL> CREATE TYPE SCOTT.COURSE_NST_TB AS TABLE OF SCOTT.COURSE_OBJ;
  2  /

Type created.

Step:- 3 Created a table and reference Nested Table (Scott.Course_Nst_Tb)  as a column in table. See the STORE AS clause of the Table definition. We can use USER_TYPES dictionary table to check information
Of TYPES created by user.

SQL> CREATE TABLE SCOTT.STU_COURSE_INFO(STU_ID NUMBER,STU_NAME VARCHAR2(40),COURSE_INFO SCOTT.COURSE_NST_TB)
  NESTED TABLE COURSE_INFO STORE AS COURSE_INFO;

Table created.
Elapsed: 00:00:00.29

Insert into Scott.Stu_Course_info

SQL> Insert Into Scott.Stu_Course_info Values (1,'ABC',scott.course_nst_tb(scott.course_OBJ(1,'Eelementry English')));

Insert into scott.Stu_course_info values (103,'SBX',scott.COURSE_NST_TB(scott.COURSE_OBJ(103,1001,'Elementry Physics')))
Insert into scott.Stu_course_info values (103,'SBX',scott.COURSE_NST_TB(scott.COURSE_OBJ(103,1002,'Elementry Science')))
Insert into scott.Stu_course_info values (103,'SBX',scott.COURSE_NST_TB(scott.COURSE_OBJ(103,1003,'Elementry Math')))
Insert into scott.Stu_course_info values (103,'SBX',scott.COURSE_NST_TB(scott.COURSE_OBJ(103,1004,'Elementry Chemistry')))
Insert into scott.Stu_course_info values (103,'SBX',scott.COURSE_NST_TB(scott.COURSE_OBJ(103,1005,'Elementry Pyscology')))
Insert into scott.Stu_course_info values (102,'ABC',scott.COURSE_NST_TB(scott.COURSE_OBJ(102,1001,'Elementry Physics')))
Insert into scott.Stu_course_info values (102,'ABC',scott.COURSE_NST_TB(scott.COURSE_OBJ(102,1002,'Elementry Science')))
Insert into scott.Stu_course_info values (102,'ABC’,scott.COURSE_NST_TB(scott.COURSE_OBJ(102,1003,'Elementry Math')))
Insert into scott.Stu_course_info values (102,'ABC',scott.COURSE_NST_TB(scott.COURSE_OBJ(102,1004,'Elementry Chemistry')))
Insert into scott.Stu_course_info values (102,'ABC',scott.COURSE_NST_TB(scott.COURSE_OBJ(102,1005,'Elementry Pyscology')))
(101,'XYZ',scott.COURSE_NST_TB(scott.COURSE_OBJ(101,1001,'Elementry Physics')))
Insert into scott.Stu_course_info values (101,'XYZ',scott.COURSE_NST_TB(scott.COURSE_OBJ(101,1002,'Elementry Science')))
Insert into scott.Stu_course_info values (101,'XYZ’,scott.COURSE_NST_TB(scott.COURSE_OBJ(101,1003,'Elementry Math')))
Insert into scott.Stu_course_info values (101,'XYZ',scott.COURSE_NST_TB(scott.COURSE_OBJ(101,1004,'Elementry Chemistry')))
Insert into scott.Stu_course_info values (101,'XYZ',scott.COURSE_NST_TB(scott.COURSE_OBJ(101,1005,'Elementry Pyscology')))

Elapsed: 00:00:00.01
SQL> Commit ;

Commit complete.

Elapsed: 00:00:00.00
SELECT * FROM SCOTT.STU_COURSE_INFO where stu_id='101'

STU_ID              STU_NAME                     COURSE_INFO
101                          XYZ                                      SCOTT.COURSE_NST_TB('SCOTT.COURSE_OBJ(101,1001,'Elementry Physics')')                                   
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        
101                          XYZ                                      SCOTT.COURSE_NST_TB('SCOTT.COURSE_OBJ(101,1002,'Elementry Science')')                                        
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              
101                                  XYZ                                      SCOTT.COURSE_NST_TB('SCOTT.COURSE_OBJ(101,1003,'Elementry Math')')                                       
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       
101                         XYZ                                      SCOTT.COURSE_NST_TB('SCOTT.COURSE_OBJ(101,1004,'Elementry Chemistry')')                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          

101                                 XYZ                                      SCOTT.COURSE_NST_TB('SCOTT.COURSE_OBJ(101,1005,'Elementry Pyscology')')                                                        

Now! Here lies the little complexity. You cannot see the actual value of a NESTED type column by merely referencing column  in SELECT clause.
If  we fire any select statement having a column of Nested Type , The result set will be shown just like above.
The correct way to select any column defined as NESTED type follows:

Select sci.stu_id,sci.stu_name,x.* from scott.stu_course_info sci,table(sci.course_info)x

STU_ID                 STU_NAME                                 STU_ID                 COURSE_ID              COURSE_NAME  
---------------------- ---------------------------------------- ---------------------- ---------------------- -------------
103                           SBX                                      103                    1001                   Elementry Physics                       
103                           SBX                                      103                    1002                   Elementry Science                       
103                           SBX                                      103                    1003                   Elementry Math                          
103                           SBX                                      103                    1004                   Elementry Chemistry                     
103                           SBX                                      103                    1005                   Elementry Pyscology                      
101                           XYZ                                      101                    1001                   Elementry Physics                       
101                           XYZ                                      101                    1002                   Elementry Science                       
101                           XYZ                                      101                    1003                   Elementry Math                          
101                           XYZ                                      101                    1004                   Elementry Chemistry                     
101                           XYZ                                      101                    1005                   Elementry Pyscology                     
102                           ABC                                      102                    1001                   Elementry Physics                       
102                         ABC                                        102                    1002                   Elementry Science                       
102                          ABC                                      102                    1003                   Elementry Math                          
102                          ABC                                      102                    1004                   Elementry Chemistry                     
102                          ABC                                      102                    1005                   Elementry Pyscology                



To select any particular value:
SELECT SCI.STU_ID,SCI.STU_NAME,X.COURSE_ID,X.COURSE_NAME FROM SCOTT.STU_COURSE_INFO SCI,TABLE(SCI.COURSE_INFO) X

STU_ID                 STU_NAME                                     COURSE_ID              COURSE_NAME  
---------------------- ---------------------------------------- ---------------------- ---------------------- -------------
101                              XYZ                                                            1001                   Elementry Physics                       
101                              XYZ                                        1002                   Elementry Science                       
101                             XYZ                                                       1003                   Elementry Math                          
101                             XYZ                                                         1004                   Elementry Chemistry                     
101                             XYZ                                                         1005                   Elementry Pyscology                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      

To select any particular value
SELECT SCI.STU_ID,SCI.STU_NAME,X.COURSE_ID,X.COURSE_NAME FROM SCOTT.STU_COURSE_INFO SCI,TABLE(SCI.COURSE_INFO) X
WHERE X.STU_ID=SCI.STU_ID
AND X.STU_ID=101         

update
To update a table having a column defined as NESTED type, we need to define a MAP method of Object.

  1   Update scott.stu_course_info sci
  2   set sci.course_info=Scott.Course_Nst_tb(Scott.Course_obj(101,1003,'elementry math'))
  3*  where  course_info=scott.course_nst_tb(scott.course_obj(101,1003,'Elementry Math'))
SQL> /

1 row updated.


SELECT SCI.STU_ID,SCI.STU_NAME,X.COURSE_ID,X.COURSE_NAME FROM SCOTT.STU_COURSE_INFO SCI,TABLE(SCI.COURSE_INFO) X
WHERE X.STU_ID=SCI.STU_ID
AND X.STU_ID=101
and x.course_name like '%ath%'

STU_ID                 STU_NAME                                     COURSE_ID              COURSE_NAME  
---------------------- ---------------------------------------- ---------------------- ---------------------- -------------
101                             XYZ                                                       1003                   elementry math                          

Delete

delete from scott.stu_course_info sci
 where course_info=scott.course_nst_tb(scott.course_obj(101,1003,'Elementry Math'))

commit

SELECT SCI.STU_ID,SCI.STU_NAME,X.COURSE_ID,X.COURSE_NAME FROM SCOTT.STU_COURSE_INFO SCI,TABLE(SCI.COURSE_INFO) X
WHERE X.STU_ID=SCI.STU_ID
AND X.STU_ID=101
order by 1,3

STU_ID                 STU_NAME                                     COURSE_ID              COURSE_NAME  
---------------------- ---------------------------------------- ---------------------- ---------------------- -------------
101                         RAJ                                                         1002                       Elementry Science
101                         RAJ                                                         1004                       Elementry Chemistry
101                         RAJ                                                         1005                       Elementry Pyscology


As we can see, that it is really not that complicated or difficult to use NESTED type or Varry Type using in SQL Statement.  We can use is pretty easily once we start using it. In part 2 we will discuss the performance impact of using NESTED types as columns..

Any suggestion, correction, comments will be appreciated.

No comments:

Post a Comment