Satyaki De - SQL Exploration

I'm a software engineer. I love my Oracle more than me. And, i'm senior forum member in OTN from Dec 2006 and completed my OCA. This blog mainly deals with Oracle & it's relevant technologies from useful perspective. Currently, I'm working as Teradata & Informatica ETL Solution designer. And, also take part in Teradata forum discussion.

In the previous post we have discussed about generating an XML file using Oracle SQL XML functions. Today we will do that in reverse manner. That means we will load the data generated by that query in the database tables.

At the end of this post (Which is a continue of the previous post) - you will be successfully generate an XML file from Oracle Tables & also able to load the data from XML on that same structured tables. So, that will complete the full life cycle of XML in oracle(Obviously concentrate on some basics).

Lets see -

Our main ingredients for this class - is the XML file named - emp_oracle.xml

And, it looks like -

<?xml version="1.0" encoding="UTF-8"?>
<EmployeeList>
  <Emp>
      <Employee_ID>200</Employee_ID>
      <First>Whalen</First>
      <Sal>4400</Sal>
      <HireDate>1987-09-17</HireDate>
  </Emp>
  <Emp>
      <Employee_ID>201</Employee_ID>
      <First>Billy</First>
      <Sal>4500</Sal>
      <HireDate>1985-06-10</HireDate>
  </Emp>
  <Emp>
      <Employee_ID>202</Employee_ID>
      <First>Bireswar</First>
      <Sal>9000</Sal>
      <HireDate>1978-06-10</HireDate>
  </Emp>
</EmployeeList>
We need to create one Oracle Directories to map with the Operating System directories in the following manner ->

sys@ORCL>
sys@ORCL>select * from v$version;

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

Elapsed: 00:00:00.00
sys@ORCL>
sys@ORCL>
sys@ORCL>CREATE OR REPLACE DIRECTORY SATY_DIR AS 'D:\XML_Output'
  2  /

Directory created.

Elapsed: 00:00:00.23
sys@ORCL>
sys@ORCL>GRANT READ, WRITE ON DIRECTORY SATY_DIR TO SCOTT, HR;

Grant succeeded.

Elapsed: 00:00:00.08
sys@ORCL>

Once you have created the directory successfully and give the proper privileges to the users like Scott or Hr - you have completed one important component of today's test. Still we are far to go. Now the second part is -

scott@ORCL>
scott@ORCL>select * from v$version;

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

Elapsed: 00:00:00.00
scott@ORCL>
scott@ORCL>
scott@ORCL>CREATE TABLE t
  2   (
  3     serialNo  NUMBER(10),
  4     fileName  VARCHAR2(100),
  5     xml       XMLTYPE,
  6     constraints pk_serialNo primary key(serialNo)
  7   );

Table created.

Elapsed: 00:00:04.13
scott@ORCL>
scott@ORCL>
scott@ORCL>CREATE SEQUENCE x_seq
  2  START WITH 1
  3  INCREMENT BY 1;

Sequence created.

Elapsed: 00:00:00.31
scott@ORCL>
scott@ORCL>CREATE OR REPLACE PROCEDURE load_xml(
  2                                        p_dir       IN  VARCHAR2,
  3                                        p_filename  IN  VARCHAR2
  4                                      )
  5  IS
  6    l_bfile  BFILE := BFILENAME(p_dir, p_filename);
  7    l_clob   CLOB;
  8  BEGIN
  9    DBMS_LOB.createtemporary (l_clob, TRUE);
 10
 11    DBMS_LOB.fileopen(l_bfile, DBMS_LOB.file_readonly);
 12    DBMS_LOB.loadfromfile(l_clob, l_bfile, DBMS_LOB.getlength(l_bfile));
 13    DBMS_LOB.fileclose(l_bfile);
 14
 15    INSERT INTO t(
 16                   serialNo,
 17                   fileName,
 18                   xml
 19                 )
 20    VALUES (
 21             x_seq.NEXTVAL,
 22             p_filename,
 23             XMLTYPE.createXML(l_clob)
 24           );
 25
 26    COMMIT;
 27
 28    DBMS_LOB.freetemporary(l_clob);
 29  END;
 30  /

Procedure created.

Elapsed: 00:00:00.88
scott@ORCL>
scott@ORCL>EXEC load_xml(p_dir => 'SATY_DIR', p_filename => 'emp_oracle.xml');

PL/SQL procedure successfully completed.

Elapsed: 00:00:00.16
scott@ORCL>
scott@ORCL>set long 5000
scott@ORCL>
scott@ORCL>set pagesize 0
scott@ORCL>
scott@ORCL>select xml from t;
<?xml version="1.0" encoding="UTF-8"?>
<EmployeeList>
  <Emp>
      <Employee_ID>200</Employee_ID>
      <First>Whalen</First>
      <Sal>4400</Sal>
      <HireDate>1987-09-17</HireDate>
  </Emp>
  <Emp>
      <Employee_ID>201</Employee_ID>
      <First>Billy</First>
      <Sal>4500</Sal>
      <HireDate>1985-06-10</HireDate>
  </Emp>
  <Emp>
      <Employee_ID>202</Employee_ID>
      <First>Bireswar</First>
      <Sal>9000</Sal>
      <HireDate>1978-06-10</HireDate>
  </Emp>
</EmployeeList>


Elapsed: 00:00:00.10
scott@ORCL>

Ok. So, we've initially load the data into the temp table t. But, we need to load the data from this temp table t to our target table revive_xml which will look like -

scott@ORCL>create table revive_xml
  2   (
  3     rev_emp_id   number(4),
  4     rev_f_name   varchar2(40),
  5     rev_salary   number(10,2),
  6     rev_jn_dt    date,
  7     constraints pk_rev_emp_id primary key(rev_emp_id)
  8   );

Table created.

Elapsed: 00:00:00.40
scott@ORCL>

Ok. So, we have done another important part of our job. Let's concentrate on our final mission -

scott@ORCL>insert into revive_xml(
  2                          rev_emp_id,
  3                          rev_f_name,
  4                          rev_salary,
  5                          rev_jn_dt
  6                        )
  7  select cast(t1.EmployeeId as number(4)) EmployeeId,
  8         t2.FirstName,
  9         cast(t3.Salary as number(10,2)) Salary,
 10         to_date(t4.JoiningDt,'YYYY-MM-DD') JoiningDt
 11  from (
 12          select rownum rn1,
 13                  extractValue(value(EmployeeId),'/Emp/Employee_ID') EmployeeId
 14          from t,
 15               table(xmlsequence(extract(xml, '/EmployeeList/Emp'))) EmployeeId
 16       ) t1,
 17       (
 18          select rownum rn2,
 19                  extractValue(value(FirstName),'/Emp/First') FirstName
 20          from t,
 21               table(xmlsequence(extract(xml, '/EmployeeList/Emp'))) FirstName
 22       ) t2,
 23       (
 24          select rownum rn3,
 25                  extractValue(value(Salary),'/Emp/Sal') Salary
 26          from t,
 27               table(xmlsequence(extract(xml, '/EmployeeList/Emp'))) Salary
 28       ) t3,
 29       (
 30          select rownum rn4,
 31                  extractValue(value(HireDate),'/Emp/HireDate') JoiningDt
 32          from t,
 33               table(xmlsequence(extract(xml, '/EmployeeList/Emp'))) HireDate
 34       ) t4
 35  where t1.rn1 = t2.rn2
 36  and   t1.rn1 = t3.rn3
 37  and   t1.rn1 = t4.rn4;

3 rows created.

Elapsed: 00:00:00.16
scott@ORCL>
scott@ORCL>commit;

Commit complete.

Elapsed: 00:00:00.22
scott@ORCL>
scott@ORCL>
scott@ORCL>select * from revive_xml;

REV_EMP_ID REV_F_NAME                               REV_SALARY REV_JN_DT
---------- ---------------------------------------- ---------- ---------
       200 Whalen                                         4400 17-SEP-87
       201 Billy                                          4500 10-JUN-85
       202 Bireswar                                       9000 10-JUN-78

scott@ORCL>

So, you have done it finally.

You can do it another way but that is limited to single record parsing -

scott@ORCL>with t
  2  as (
  3      select xmlType('
  4      <EmployeeList>
  5        <Emp>
  6        <Employee_ID>200</Employee_ID>
  7        <First>Whalen</First>
  8        <Sal>4400</Sal>
  9        <HireDate>1987-09-17</HireDate>
 10        </Emp>
 11      </EmployeeList>') xml from dual
 12    )
 13  SELECT rownum rn,
 14         a.EmployeeId,
 15         a.FirstName,
 16         a.Salary,
 17         a.JoiningDt
 18  FROM t,
 19       XMLTABLE('/EmployeeList'
 20       PASSING t.xml
 21       COLUMNS
 22          EmployeeId varchar2(10) PATH '/EmployeeList/Emp/Employee_ID',
 23          FirstName varchar2(20) PATH '/EmployeeList/Emp/First',
 24          Salary number(10) PATH '/EmployeeList/Emp/Sal',
 25          JoiningDt date PATH '/EmployeeList/Emp/HireDate'
 26        ) a;

        RN EMPLOYEEID FIRSTNAME                SALARY JOININGDT
---------- ---------- -------------------- ---------- ---------
         1 200        Whalen                     4400 17-SEP-87

scott@ORCL>
scott@ORCL>

Hope this will solve your purpose.

Also you can refer to the following XML In Oracle link.

Regards.

0 comments: