Selecting (XML) data directly from disk

5

On the OTN XMLDB Forum, a question was asked if you could directly select from a XML file on disk, or to be more precise ”
XQUERY / XMLTABLE Syntax to read and XML from a Windows local drive?“. I had the idea that this could be easily done, nowadays via XMLDB functionality. So I tried it and came to the following conclusions. Although tested on Oracle 11.1.0.6.0 on Windows, this should also work on Oracle 10.2.x.

SQL> conn test/test
Connected.
 
SQL> -- The test user has the DBA role...
 
SQL> 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 <span style="color: navy;"><strong>for</strong></span> 32-bit Windows: Version 11.1.0.6.0 - Production
NLSRTL Version 11.1.0.6.0 - Production
 
5 rows selected.
 
<span style="color: #006400;">/* The content of the data.xml file.

&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;ROOT&gt;
  &lt;ID&gt;0&lt;/ID&gt;
  &lt;INFO&gt;
    &lt;INFO_ID&gt;0&lt;/INFO_ID&gt;
    &lt;INFO_CONTENT&gt;Text&lt;/INFO_CONTENT&gt;
  &lt;/INFO&gt;
&lt;/ROOT&gt;

*/</span>
 
SQL&gt; drop directory  xmlstore;
 
Directory dropped.
 
 
SQL&gt; -- the directory is on a Windows system...
 
SQL&gt; create directory xmlstore as <span style="color: navy;">'E:\temp'</span>;
 
Directory created.
 
SQL&gt; create table test
  2  (xmldata xmltype);
 
Table created.
 
SQL&gt; INSERT into test
  2  VALUES
  3  (XMLTYPE(bfilename(<span style="color: navy;">'XMLSTORE'</span>,<span style="color: navy;">'data.xml'</span>),NLS_CHARSET_ID(<span style="color: navy;">'AL32UTF8'</span>)));
 
1 row created.
 
 
SQL&gt; set <span style="color: navy;"><strong>long</strong></span> 100000000
 
SQL&gt; select * from test;
 
XMLDATA
--------------------------------------------------------
&lt;?xml version=<span style="color: red;">"1.0"</span> encoding=<span style="color: red;">"UTF-8"</span>?&gt;
&lt;ROOT&gt;
  &lt;ID&gt;0&lt;/ID&gt;
  &lt;INFO&gt;
    &lt;INFO_ID&gt;0&lt;/INFO_ID&gt;
    &lt;INFO_CONTENT&gt;Text&lt;/INFO_CONTENT&gt;
  &lt;/INFO&gt;
&lt;/ROOT&gt;
 
 
1 row selected.
 
SQL&gt; select XMLTYPE(<span style="color: navy;">'&lt;ROOT&gt;&lt;ID&gt;0&lt;/ID&gt;&lt;INFO&gt;&lt;INFO_ID&gt;0&lt;/INFO_ID&gt;&lt;INFO_CONTENT&gt;Text&lt;/INFO_CONTENT&gt;&lt;/INFO&gt;&lt;/ROOT&gt;'</span>) as <span style="color: red;">"XDATA"</span>
  2  from dual;
 
XDATA
------------------------------------------------------------------------------------------
&lt;ROOT&gt;&lt;ID&gt;0&lt;/ID&gt;&lt;INFO&gt;&lt;INFO_ID&gt;0&lt;/INFO_ID&gt;&lt;INFO_CONTENT&gt;Text&lt;/INFO_CONTENT&gt;&lt;/INFO&gt;&lt;/ROOT&gt;
 
1 row selected.
 
 
SQL&gt; select XMLTYPE(bfilename(<span style="color: navy;">'XMLSTORE'</span>,<span style="color: navy;">'data.xml'</span>),NLS_CHARSET_ID(<span style="color: navy;">'AL32UTF8'</span>)) as <span style="color: red;">"XDATA"</span>
  2  from dual;
ERROR:
ORA-21500: internal error code, arguments: [%s], [%s], [%s], [%s], [%s], [%s], [%s], [%s]
 
 
 
no rows selected
 
 
SQL&gt; select extract((XMLTYPE(bfilename(<span style="color: navy;">'XMLSTORE'</span>,<span style="color: navy;">'data.xml'</span>),NLS_CHARSET_ID(<span style="color: navy;">'AL32UTF8'</span>))),<span style="color: navy;">'*'</span>) as <span style="color: red;">"XDATA"</span>
  2  from dual;
 
XDATA
------------------------------------------------------------------------------------------
&lt;ROOT&gt;&lt;ID&gt;0&lt;/ID&gt;&lt;INFO&gt;&lt;INFO_ID&gt;0&lt;/INFO_ID&gt;&lt;INFO_CONTENT&gt;Text&lt;/INFO_CONTENT&gt;&lt;/INFO&gt;&lt;/ROOT&gt;
 
1 row selected.
 
SQL&gt; select xdata
  2  from (XMLTABLE(<span style="color: navy;">'*'</span>
  3                 PASSING (XMLTYPE(bfilename(<span style="color: navy;">'XMLSTORE'</span>,<span style="color: navy;">'data.xml'</span>),NLS_CHARSET_ID(<span style="color: navy;">'AL32UTF8'</span>)))
  4                 COLUMNS xdata xmltype PATH <span style="color: navy;">'/*'</span>
  5                )
  6       )
  7  ;
 
XDATA
------------------------------------------------------------------------------------------
&lt;ROOT&gt;&lt;ID&gt;0&lt;/ID&gt;&lt;INFO&gt;&lt;INFO_ID&gt;0&lt;/INFO_ID&gt;&lt;INFO_CONTENT&gt;Text&lt;/INFO_CONTENT&gt;&lt;/INFO&gt;&lt;/ROOT&gt;

 

Cheers

 

Marco

Share.

About Author

Marco Gralike, working for AMIS Services BV as a Principal Oracle Database Consultant in the Netherlands, has experience as a DBA since 1994 (Oracle 6). Marco is also eager and skillful in other fields, like Operating System Administration and Application Servers, mainly to find working, performing solutions. Marco has been specializing in Oracle XMLDB, since 2003, focusing on his old love, database administration and performance. He is an Oracle XMLDB enthusiast ever since. He is also a dedicated contributor of the Oracle User Group community, helping people with their steep XMLDB learning curve. To this purpose, Marco also devoted his personal blog site to XMLDB and other Oracle issues. Marco is a member of the OakTable network and an Oracle ACE Director (specialization Oracle XMLDB).

5 Comments

  1. Karin Kriebisch on

    Hello Marco,
    I have some questions about your article:
    Can give any indication about the performance of this read action? Where is the greatest restriction in the performance?
    Are there any restrictions on the file sizes other than the OS?
    And in which circumstances would you preferably use this technique?

    Cheers,
    Karin

  2. On 10.2.0.2.0 it works without the extract. Note by the way how the encoding is changed to “ISO-8859-1″

    [pre]

    PGI@pgio> select XMLTYPE(bfilename(‘XMLSTORE’,’data.xml’),NLS_CHARSET_ID(‘AL32UTF8′)) as “XDATA”
    2 from dual
    3 /

    XDATA
    ——————————————————————————–

    0

    0
    Text

    [/pre]

  3. Marco Gralike on

    A drive local to your database server. No, it also works for other operating systems (adjust your directory alias accordingly).

  4. Nice, but it raise some questions:

    What is a “Windows local drive”? A drive local to your database server? A drive local to your database client?
    Is the above code only working for Windows?