Sunday, 25 October 2015

How Nested Tables can be stored and retrieved in a Normal table-ORACLE PL/SQL

Author:VibinDas        

 As we all know, Nested Tables (especially the Oracle Collections) can be considered as one of the advanced concepts in Oracle. In many instances we may have to deal with Nested tables and Varrays in our coding where the requirement may be to save and retrieve a set or a bundle of values in database columns. One of the benefits of using this way is that, if we have multiple values to be stored corresponding to one subject or entity, these multiple values of each particular subject can be treated as a single entity and stored as a single value in database table.
Sometimes this introduction may bring a little bit of complexity in your mind; but the real fact is that, this is a very simple and interesting topic which you are going to enjoy for sure.
Let’s start with an example on this. Consider a STUDENT table which stores the information like the student id, first name, last name, his class etc... It’s very pretty simple as below.

Step 1 : First create a test table as below.
CREATE TABLE TEMP_STUDENT_DTLS
(
   STUD_ID NUMBER,
   STUD_NAME VARCHAR2(30),
   STUD_CLASS NUMBER
);

Step 2 : Insert some entries to it.
INSERT INTO TEMP_STUDENT_DTLS(STUD_ID,STUD_NAME,STUD_CLASS)
           VALUES(100, 'JAMES', 10);
INSERT INTO TEMP_STUDENT_DTLS(STUD_ID,STUD_NAME,STUD_CLASS)
           VALUES(200, 'ALBERT', 8);
INSERT INTO TEMP_STUDENT_DTLS(STUD_ID,STUD_NAME,STUD_CLASS)
           VALUES(300, 'MIKE', 5);
INSERT INTO TEMP_STUDENT_DTLS(STUD_ID,STUD_NAME,STUD_CLASS)
           VALUES(400, 'THOMAS', 2);
COMMIT;
**** 4 Rows inserted and committed.
Step 3 : Verifying the inserted records.
STUD_ID
STUD_NAME
STUD_CLASS
100
JAMES
10
200
ALBERT
8
300
MIKE
5
400
THOMAS
2
 So far everything is fine here. No weird things. But it’s going to come soon.
Suppose the requirement has got changed slightly and the additional thing is as follows
·         Need to store the subject list and corresponding mark of each student as well in the table.

Do you see anything fishy here? If each of the students are having same number of subjects, then it would been somewhat possible -  for example, if there are only 3 subjects for all students, we could have created 6 more columns such as SUB1, MARK1, SUB2, MARK2, SUB3, MARK3. But here since each of these students are in different classes, the number of subjects won’t be the same for everyone. For example, James being in 10th standard will have 12 subjects to study whereas Thomas will have only 4 subjects as he is in 2nd standard.

Here two approaches are in hand - One is to go for normalization and the second to go with Nested table concepts. If we are in a position not to split the table further, we can’t go for normalization. Now the only solution left is to go with Nested tables.
Solution Using Nested Table
Data Loading
      Since we need to store the (Subject, Mark) pair information corresponding to each subject, we need to first declare a Type object which is capable of storing Subject name and Mark as single.
Step 1 : Creation of an OBJECT Type
CREATE TYPE OBJ_TYPE_SUBJ_MARK IS OBJECT
(
   SUBJECT_NAME VARCHAR2(30),
   MARK NUMBER
);
Step 2 : Creation of a Nested Table Type
CREATE TYPE NT_SUBJ_MARK_DTLS IS TABLE OF OBJ_TYPE_SUBJ_MARK;
  By doing this, a one dimensional array ‘NT_SUBJ_MARK_DTLS’ is created where each cell can carry (SUBJECT, MARK) value combination.
NT_SUBJ_MARK_DTLS
(SUBJECT_NAME1, MARK1)
(SUBJECT_NAME2, MARK2)
 (SUBJECT_NAME3, MARK3)
(SUBJECT_NAME4, MARK4)
(SUBJECT_NAME5, MARK5)
(SUBJECT_NAME6, MARK6)
.
.
.
.
        
  Actually there is no restriction on the size of this one dimensional array. For the time being, showed 6 elements only. However it can be any of any size according to the number of values we insert into the column.
Step 3 : Recreation of table with one column as this newly created Nested Table
          Now recreate the same table with one additional column which will carry the Subject and Mark details of each student in an array format. For that, the column should be having data type of “NT_SUBJ_MARK_DTLS” as given below.
DROP TABLE TEMP_STUDENT_DTLS PURGE;

CREATE TABLE TEMP_STUDENT_DTLS
(
   STUD_ID           NUMBER,
   STUD_NAME      VARCHAR2(30),
   STUD_CLASS     NUMBER,
   MARK_DTLS      NT_SUBJ_MARK_DTLS
) NESTED TABLE MARK_DTLS STORE AS SYS_GEN_TBL;
 Datatype of column is NT_SUBJ_MARK_DTLS which is nothing but the Nested table we created
Here the keyword ‘NESTED TABLE’ is used to inform Oracle that the column is having data type of a Nested table (which we have already created). One additional point to remember here is that, while declaring a database column of such a user defined data type of Nested Table, internally the contents of that column are not stored along with the remaining table column values. Instead, they are stored in another System generated table space allocated by Oracle which we need to name and in our example, the name ‘SYS_GEN_TBL’ has been given for that. This has to be given followed by the keyword ’STORE AS’.

Step 2 : Insert some entries to it.
   Suppose the Subject- Mark details of each of the students are as follows.
·         James
Marks 45, 40, 35 and 42 for Subjects Physics, Maths, English and Literature respectively.

·         Albert
Marks 48, 33 and 50 for Subjects Chemistry, Maths, and Latin respectively.

·         Thomas
Marks 38 and 42 for Subjects History and Maths respectively.

Hence the entries are like these.
INSERT INTO TEMP_STUDENT_DTLS(STUD_ID,
                               STUD_NAME,
                               STUD_CLASS,
                               MARK_DTLS)
      VALUES(100,
                  'JAMES',
                  10,
                  NT_SUBJ_MARK_DTLS(
                                              OBJ_TYPE_SUBJ_MARK ('PHYSICS', 45),
                                              OBJ_TYPE_SUBJ_MARK ('MATHS', 40),
                                              OBJ_TYPE_SUBJ_MARK ('ENGLISH', 35),
                                              OBJ_TYPE_SUBJ_MARK ('LITERATURE', 42)
                                             )
                );

INSERT INTO TEMP_STUDENT_DTLS(STUD_ID,
                               STUD_NAME,
                               STUD_CLASS,
                               MARK_DTLS)
      VALUES(200,
                  'ALBERT',
                  8,
                  NT_SUBJ_MARK_DTLS(
                                              OBJ_TYPE_SUBJ_MARK ('CHEMISTRY', 48),
                                              OBJ_TYPE_SUBJ_MARK ('MATHS', 33),
                                              OBJ_TYPE_SUBJ_MARK ('LATIN', 50)
                                             )
                );


INSERT INTO TEMP_STUDENT_DTLS(STUD_ID,
                               STUD_NAME,
                               STUD_CLASS,
                               MARK_DTLS)
      VALUES(400,
                  'THOMAS',
                  2,
                  NT_SUBJ_MARK_DTLS(
                                              OBJ_TYPE_SUBJ_MARK ('HISTORY', 38),
                                              OBJ_TYPE_SUBJ_MARK ('MATHS', 42)
                                             )
                );

COMMIT;
 *****3 Rows inserted and committed.

Step 3 : Verifying the inserted records.
SELECT * FROM TEMP_STUDENT_DTLS;
STUD_ID
STUD_NAME
STUD_CLASS
MARK_DTLS
100
JAMES
10
(DATASET)
200
ALBERT
8
(DATASET)
400
THOMAS
2
(DATASET)


As can be seen, the multiple Subjects and their corresponding marks have been loaded to a single column. Thus there is no need of any replication of same student record for each and every subject.
Data Retrieval
·        SELECT
  In order to get the subject-mark details of James, we need to use the TABLE operator as below.
SELECT *
  FROM TABLE(
                        SELECT MARK_DTLS
                           FROM TEMP_STUDENT_DTLS
                            WHERE STUD_NAME = 'JAMES'
                      );
SUBJECT_NAME
MARK
PHYSICS
45
MATHS
40
ENGLISH
35
LITERATURE
42

·        INSERT
On the other hand, if our intention is add to add one more subject-mark details to James, then
INSERT INTO TABLE(
                        SELECT MARK_DTLS
                           FROM TEMP_STUDENT_DTLS
                            WHERE STUD_NAME = 'JAMES'
                      )
                        VALUES('CHEMISTRY',46);

COMMIT;
****   1 Row inserted and committed

.
To get the subject-mark details of James,
SELECT *
  FROM TABLE(
                        SELECT MARK_DTLS
                           FROM TEMP_STUDENT_DTLS
                            WHERE STUD_NAME = 'JAMES'
                      );
SUBJECT_NAME
MARK
PHYSICS
45
MATHS
40
ENGLISH
35
LITERATURE
42
CHEMISTRY
46

·        DELETE
In order to delete the subject = ‘CHEMISTRY’ record,
DELETE
  FROM TABLE(
                        SELECT MARK_DTLS
                           FROM TEMP_STUDENT_DTLS
                            WHERE STUD_NAME = 'JAMES'
                      )
           WHERE SUBJECT_NAME = 'CHEMISTRY';

COMMIT;
   1 Row deleted and committed
To get the subject-mark details of James,
SELECT *
  FROM TABLE(
                        SELECT MARK_DTLS
                           FROM TEMP_STUDENT_DTLS
                            WHERE STUD_NAME = 'JAMES'
                      );
SUBJECT_NAME
MARK
PHYSICS
45
MATHS
40
ENGLISH
35
LITERATURE
42


·        UPDATE
In order to update the mark of  subject = ‘PHYSICS’ record from current value of 45 to 50,
UPDATE TABLE(
                        SELECT MARK_DTLS
                           FROM TEMP_STUDENT_DTLS
                            WHERE STUD_NAME = 'JAMES'
                      )
       SET MARK = 50
         WHERE SUBJECT_NAME = 'PHYSICS';

COMMIT;
   1 Row update and committed
To get the subject-mark details of James,
SELECT *
  FROM TABLE(
                        SELECT MARK_DTLS
                           FROM TEMP_STUDENT_DTLS
                            WHERE STUD_NAME = 'JAMES'
                      );
SUBJECT_NAME
MARK
PHYSICS
50
MATHS
40
ENGLISH
35
LITERATURE
42

Since we are making use of NESTED Table, the details are saved in the database itself as database table columns.

If you like this post, please share it on google by clicking on the Google +1 button.

Please go through similar Oracle Posts @DWHLAUREATE:




Sunday, 16 August 2015

Use of the property FORWARDING REJECTED ROWS in an Update Strategy transformation??

When we use the update strategy transformation we have the option to reject the row based on a criteria. We usually use DECODE or IIF to specify the criteria for rejecting the row[Treat Source Row should be selected as Data Driven at the session level]

IIF( ( RESIDENT_SK=0), DD_REJECT, DD_UPDATE )

The following table lists the constants for each database operation and their numeric equivalent:
Insert
DD_INSERT (Numeric Value 0)
Update
DD_UPDATE (Numeric Value 1)
Delete
DD_DELETE (Numeric Value 2)
Reject
 DD_REJECT (Numeric Value 3)

Now coming to the Forwarding Rejected Row Option in update strategy, this option is used to forward the rejected rows into the bad file which we define at session level. If you disable this option, the rejected records won't be available in the bad file (reject file).

However the rejected rows will be available in session log (Normal logging level) even though the forwarding rejected row option is enabled\disabled.

These records in the reject file help us to understand the reason for rejection and validate the records not satisfying the business requirement. This helps to change the input data the next time we load the target

Structure of Informatica Bad Files or Reject Files
There are two types of Indicators in the reject file. One is the Row Indicator and the other is the Column Indicator.
List of Values of Row Indicators:
Row Indicator
Indicator Significance
Rejected By
0
Insert
Writer or target
1
Update
Writer or target
2
Delete
Writer or target
3
Reject
Writer
4
Rolled-back insert
Writer
5
Rolled-back update
Writer
6
Rolled-back delete
Writer
7
Committed insert
Writer
8
Committed update
Writer
9
Committed delete
Writer

Saturday, 27 June 2015

Calculated Percentage Column always showing result as 0% Zero Percentage in OBIEE 11g

You may also face similar issue while upgrading OBIEE to a newer version or if you upgrade some of your dashboards from OBIEE 10.1.3.4 to 11.1.1.5. The issue is that, some of the calculations under certain columns in the reports were showing zeros instead of the calculated values.  The requirement was to calculate a match rate % for some data based on another field that showed 'MATCH' or 'NO MATCH'. 
 The real-time scenario was
(SUM(CASE Table1.Column1 WHEN 'MATCH' THEN 1 ELSE 0 END)/COUNT(Table1.Column1))*100

However, this was returning 0% as the result. With the help of some blogs and questions raised on OBIEE threads I came to know that this happens when you have an integer in a calculation. The solution which I used is very simple and was successful in achieving the requirement. The very easy fix to this issue is to multiply the calculation by 1.0.  The updated calculation which works is shown below and provides a meaningful result.
(don't use 1, as this will not work.  Use 1.0)

((1.0*SUM(CASE Table1.Column1 WHEN 'MATCH' THEN 1 ELSE 0 END))/(1.0*COUNT(Table1.Column1)))*100

Saturday, 25 April 2015

Informatica Repository Query to Find All the Source and Target connections in Your Respository

The below Informatica repository query can be used to get the Source Connections, Target connections of all the instances used in the informatica.

Apart from that we have details of the Folder, mapping name ,session name , and the connection name as shown in Informatica.

SELECT DISTINCT 

C.SUBJECT_AREA FOLDER_NAME, 
C.MAPPING_NAME MAPPING_NAME, 
C.SESSION_NAME SESSION_NAME, 
E.READER_WRITER_TYPE, 
E.INSTANCE_NAME, 
E.CNX_NAME, 

CASE 
WHEN E.WIDGET_TYPE = 2 
THEN
'TARGET CONNECTION' 
ELSE 
CASE 
WHEN E.WIDGET_TYPE IN
(1, 3, 56, 45, 55, 84) 
THEN 
'SOURCE CONNECTION' 
ELSE 
NULL 
END 
END CNX_TYPE 

FROM INFA_REPO.REP_VERSION_PROPS A, 
     INFA_REPO.REP_USERS B, 
     INFA_REPO.REP_LOAD_SESSIONS C, 
     INFA_REPO.REP_REPOSIT_INFO D, 
     INFA_REPO.REP_SESS_WIDGET_CNXS E 

WHERE ( A.USER_ID = B.USER_ID 
AND C.SESSION_ID <> D.REPOSITORY_ID 
AND C.SESSION_ID = A.OBJECT_ID 
AND C.SUBJECT_ID = A.SUBJECT_ID 
AND A.OBJECT_TYPE = 68 
AND C.SESSION_ID = E.SESSION_ID 
AND C.SESSION_VERSION_NUMBER = 
E.SESSION_VERSION_NUMBER)

Related Posts Plugin for WordPress, Blogger...

ShareThis