Selecting the entire Database as XML String

2012-01-13 - General, XML

I just ran into this question on StackOverflow: Dump data into single XML file from MS SQL Server 2008 R2.
In there Daniel is looking for a solution to export his database as an XML file.

I thought that request was an excellent way to practice my XML skills so I spend a little time to come up with a solution.

For testing purposes I first created a few tables in an empty database:

<p>DECLARE @cmd NVARCHAR(MAX) ;<br />
                    + '(id INT IDENTITY(1,1)'<br />
                    + (SELECT   ',c' + CAST(c.n AS NVARCHAR(MAX))<br />
                                + ' INT DEFAULT ' + CAST(c.n AS NVARCHAR(MAX))<br />
                                + '*' + CAST(t.n AS NVARCHAR(MAX))<br />
                       FROM     dbo.GetNums(( t.n - 1 ) % 10 + 1) c<br />
             FOR    XML PATH('') ,<br />
                        TYPE).value('.', 'NVARCHAR(MAX)') + ');INSERT INTO T'<br />
                    + CAST(n AS NVARCHAR(MAX)) + ' DEFAULT VALUES;'<br />
             FROM   dbo.GetNums (3000) t<br />
FOR XML PATH('') ,<br />
        TYPE).value('.', 'NVARCHAR(MAX)') ;</p>
<p>EXEC(@cmd) ;<br />

This snippet uses Itzik's GetNums function to generate 3000 CREATE TABLE and INSERT statements.

With the table in place I was able to come up with this solution to the original question:

<br />
SET @cmd = 'SELECT * FROM('<br />
    + STUFF(<br />
        + '.' + QUOTENAME(name) + ''' [@name],' + '(SELECT * FROM '<br />
        + QUOTENAME(OBJECT_SCHEMA_NAME(object_id)) + '.' + QUOTENAME(name)<br />
        + ' FOR XML PATH(''row''),TYPE) data'<br />
 FROM   sys.tables<br />
    FOR     XML PATH('') ,<br />
                TYPE).value('.', 'NVARCHAR(MAX)'), 1, 11, '')<br />
    + ')X FOR XML PATH(''table''),TYPE;' ;</p>
<p>EXEC(@cmd) ;<br />

The script builds a single statement. For each table it selects the table name in a column with the name [@name] and the content of that table as XML (using a sub-select) in a column with the name data. All these SELECTs are "UNION ALL"ed together and formated into the final XML document with an additional outer SELECT FOR XML.

If you are only after some of the tables, you can add a where clause in row 8 of the above snippet.

The resulting XML has this format:

<br />
&amp;lt;table name=&amp;quot;[dbo].[T1628]&amp;quot;&amp;gt;<br />
  &amp;lt;data&amp;gt;<br />
    &amp;lt;row&amp;gt;<br />
      &amp;lt;id&amp;gt;1&amp;lt;/id&amp;gt;<br />
      &amp;lt;c1&amp;gt;1628&amp;lt;/c1&amp;gt;<br />
      &amp;lt;c2&amp;gt;3256&amp;lt;/c2&amp;gt;<br />
      &amp;lt;c3&amp;gt;4884&amp;lt;/c3&amp;gt;<br />
      &amp;lt;c4&amp;gt;6512&amp;lt;/c4&amp;gt;<br />
      &amp;lt;c5&amp;gt;8140&amp;lt;/c5&amp;gt;<br />
      &amp;lt;c6&amp;gt;9768&amp;lt;/c6&amp;gt;<br />
      &amp;lt;c7&amp;gt;11396&amp;lt;/c7&amp;gt;<br />
      &amp;lt;c8&amp;gt;13024&amp;lt;/c8&amp;gt;<br />
    &amp;lt;/row&amp;gt;<br />
  &amp;lt;/data&amp;gt;<br />
&amp;lt;/table&amp;gt;<br />
&amp;lt;table name=&amp;quot;[dbo].[T2102]&amp;quot;&amp;gt;<br />
  &amp;lt;data&amp;gt;<br />
    &amp;lt;row&amp;gt;<br />
      &amp;lt;id&amp;gt;1&amp;lt;/id&amp;gt;<br />
      &amp;lt;c1&amp;gt;2102&amp;lt;/c1&amp;gt;<br />
      &amp;lt;c2&amp;gt;4204&amp;lt;/c2&amp;gt;<br />
    &amp;lt;/row&amp;gt;<br />
  &amp;lt;/data&amp;gt;<br />
&amp;lt;/table&amp;gt;<br />

For each table there is a <table> tag that has a name attribut with the table name. It contains a <data> tag that in turn contains one <row> tag for every row in the table.

The only thing missing to make this valid XML is a root tag, but that should be easy to add.

Categories: General, XML
Tags: ,


I can't seem to post the XML output... I guess the forum engine filters it out.


Hi Sebastian, This is an awesome solution. Can you post a modification of the script which results in the following output: ...etc So basically the data node should be left out and the rows should contain the values as attributes as opposed to sub-nodes. This results in a lot more compact XML. Thanks.


Hi Daniel, See this new post: Selecting the entire Database as XML String – 2. I hope it answers your question. Sebastian