Export Query Results to an XML File when using SQLcl (Oracle)

When using SQLcl with Oracle Database, you can export your query results to an XML file with the SPOOL command.

Example

Here’s an example to demonstrate:

SET SQLFORMAT xml;
SPOOL '/Users/barney/data/regions.xml';
SELECT * FROM regions;
SPOOL off;
SET SQLFORMAT ansiconsole;

Here’s what it did, line by line:

  • The first line sets SQLFORMAT to xml. This ensures that our resulting .xml file does in fact contain XML.
  • The second line uses the SPOOL command to specify where the output file will be written. Be sure to change /Users/barney/data/regions.xml to a location on your system, and an appropriate file name.
  • On the third line, I ran the SQL query – the results for which I’m exporting. In this case, I exported the whole regions table.
  • Next, I turned SPOOL off.
  • Lastly, I set SQLFORMAT back to my original setting, which was ansiconsole. This is optional – you could leave it at json if you prefer, or change it to something else.

Here’s what the resulting file looks like:

<?xml version='1.0'  encoding='UTF-8' ?>
<RESULTS>
	<ROW>
		<COLUMN NAME="REGION_ID"><![CDATA[1]]></COLUMN>
		<COLUMN NAME="REGION_NAME"><![CDATA[Europe]]></COLUMN>
	</ROW>
	<ROW>
		<COLUMN NAME="REGION_ID"><![CDATA[2]]></COLUMN>
		<COLUMN NAME="REGION_NAME"><![CDATA[Americas]]></COLUMN>
	</ROW>
	<ROW>
		<COLUMN NAME="REGION_ID"><![CDATA[3]]></COLUMN>
		<COLUMN NAME="REGION_NAME"><![CDATA[Asia]]></COLUMN>
	</ROW>
	<ROW>
		<COLUMN NAME="REGION_ID"><![CDATA[4]]></COLUMN>
		<COLUMN NAME="REGION_NAME"><![CDATA[Middle East and Africa]]></COLUMN>
	</ROW>
</RESULTS>
4 rows selected. 

Remove Feedback

You can remove the X rows selected with SET FEEDBACK off:

SET SQLFORMAT xml;
SET FEEDBACK off;
SPOOL '/Users/barney/data/regions_feedback_off.xml';
SELECT * FROM regions;
SPOOL off;
SET FEEDBACK on;
SET SQLFORMAT ansiconsole;

Result:

<?xml version='1.0'  encoding='UTF-8' ?>
<RESULTS>
	<ROW>
		<COLUMN NAME="REGION_ID"><![CDATA[1]]></COLUMN>
		<COLUMN NAME="REGION_NAME"><![CDATA[Europe]]></COLUMN>
	</ROW>
	<ROW>
		<COLUMN NAME="REGION_ID"><![CDATA[2]]></COLUMN>
		<COLUMN NAME="REGION_NAME"><![CDATA[Americas]]></COLUMN>
	</ROW>
	<ROW>
		<COLUMN NAME="REGION_ID"><![CDATA[3]]></COLUMN>
		<COLUMN NAME="REGION_NAME"><![CDATA[Asia]]></COLUMN>
	</ROW>
	<ROW>
		<COLUMN NAME="REGION_ID"><![CDATA[4]]></COLUMN>
		<COLUMN NAME="REGION_NAME"><![CDATA[Middle East and Africa]]></COLUMN>
	</ROW>
</RESULTS>

In this case I turned FEEDBACK back on after exporting the file.

Append the Results

By default, SPOOL uses REPLACE, which replaces the file if it already exists.

However, we can use the APPEND argument to append the results to the file.

Example:

SET SQLFORMAT xml;
SET FEEDBACK off;
SPOOL '/Users/barney/data/regions_feedback_off.xml' APPEND;
SELECT * FROM regions;
SPOOL off;
SET FEEDBACK on;
SET SQLFORMAT ansiconsole;

Resulting file:

<?xml version='1.0'  encoding='UTF-8' ?>
<RESULTS>
	<ROW>
		<COLUMN NAME="REGION_ID"><![CDATA[1]]></COLUMN>
		<COLUMN NAME="REGION_NAME"><![CDATA[Europe]]></COLUMN>
	</ROW>
	<ROW>
		<COLUMN NAME="REGION_ID"><![CDATA[2]]></COLUMN>
		<COLUMN NAME="REGION_NAME"><![CDATA[Americas]]></COLUMN>
	</ROW>
	<ROW>
		<COLUMN NAME="REGION_ID"><![CDATA[3]]></COLUMN>
		<COLUMN NAME="REGION_NAME"><![CDATA[Asia]]></COLUMN>
	</ROW>
	<ROW>
		<COLUMN NAME="REGION_ID"><![CDATA[4]]></COLUMN>
		<COLUMN NAME="REGION_NAME"><![CDATA[Middle East and Africa]]></COLUMN>
	</ROW>
</RESULTS>
<?xml version='1.0'  encoding='UTF-8' ?>
<RESULTS>
	<ROW>
		<COLUMN NAME="REGION_ID"><![CDATA[1]]></COLUMN>
		<COLUMN NAME="REGION_NAME"><![CDATA[Europe]]></COLUMN>
	</ROW>
	<ROW>
		<COLUMN NAME="REGION_ID"><![CDATA[2]]></COLUMN>
		<COLUMN NAME="REGION_NAME"><![CDATA[Americas]]></COLUMN>
	</ROW>
	<ROW>
		<COLUMN NAME="REGION_ID"><![CDATA[3]]></COLUMN>
		<COLUMN NAME="REGION_NAME"><![CDATA[Asia]]></COLUMN>
	</ROW>
	<ROW>
		<COLUMN NAME="REGION_ID"><![CDATA[4]]></COLUMN>
		<COLUMN NAME="REGION_NAME"><![CDATA[Middle East and Africa]]></COLUMN>
	</ROW>
</RESULTS>

This example appended the results to the file that was created (and populated) in the previous example. This resulted in the query output being duplicated in the file.

Overwrite the Existing File

We can use REPLACE to overwrite the existing file with the results of a new query:

SET SQLFORMAT xml;
SET FEEDBACK off;
SPOOL '/Users/barney/data/regions_feedback_off.xml' REPLACE;
SELECT * FROM regions;
SPOOL off;
SET FEEDBACK on;
SET SQLFORMAT ansiconsole;

Resulting file:

<?xml version='1.0'  encoding='UTF-8' ?>
<RESULTS>
	<ROW>
		<COLUMN NAME="REGION_ID"><![CDATA[1]]></COLUMN>
		<COLUMN NAME="REGION_NAME"><![CDATA[Europe]]></COLUMN>
	</ROW>
	<ROW>
		<COLUMN NAME="REGION_ID"><![CDATA[2]]></COLUMN>
		<COLUMN NAME="REGION_NAME"><![CDATA[Americas]]></COLUMN>
	</ROW>
	<ROW>
		<COLUMN NAME="REGION_ID"><![CDATA[3]]></COLUMN>
		<COLUMN NAME="REGION_NAME"><![CDATA[Asia]]></COLUMN>
	</ROW>
	<ROW>
		<COLUMN NAME="REGION_ID"><![CDATA[4]]></COLUMN>
		<COLUMN NAME="REGION_NAME"><![CDATA[Middle East and Africa]]></COLUMN>
	</ROW>
</RESULTS>

As mentioned, REPLACE is the default setting, so we could have simply omitted this argument altogether.