I have to create a table from a XML file.
The catch is that every ID can have multiple Rows.
So the table needs to look like this.
ID | ec_date | ec_description | ec_Type | ec_currency |
---|---|---|---|---|
54bd0b6f-693e-476f-a80e-0094de4cf3b4 | 27-July-2021 | Reiskosten woon-werk | XP504 | EUR |
9adfe4dd-49be-48fb-a838-009e861be8bd | 24-August-2021 | reiskosten Alkmaar-Zaandam | XP502 | EUR |
9adfe4dd-49be-48fb-a838-009e861be8bd | 26-August-2021 | reiskosten Alkmaar-Zaandam | XP502 | EUR |
This is my XML structure:
<Root>
<Data>
<Data>
<table>
<id>{54bd0b6f-693e-476f-a80e-0094de4cf3b4}</id>
<rows>
<row>
<columns>
<column name="ec_date" value="27-July-2021" type="System.DateTime" />
<column name="ec_description" value="Reiskosten woon-werk" type="System.String" />
<column name="ec_Type" value="XP504" type="System.String" />
<column name="ec_currency" value="EUR" type="System.String" />
</columns>
</row>
</rows>
<key>DefaultKey</key>
<total>145.14</total>
<AddOnKey>0</AddOnKey>
<data />
<parameters />
</table>
</Data>
</Data>
<Data>
<Data>
<table>
<id>{9adfe4dd-49be-48fb-a838-009e861be8bd}</id>
<rows>
<row>
<columns>
<column name="ec_date" value="24-August-2021" type="System.DateTime" />
<column name="ec_description" value="reiskosten Alkmaar-Zaandam" type="System.String" />
<column name="ec_Type" value="XP502" type="System.String" />
<column name="ec_currency" value="EUR" type="System.String" />
</columns>
</row>
<row>
<columns>
<column name="ec_date" value="26-August-2021" type="System.DateTime" />
<column name="ec_description" value="reiskosten Alkmaar-Zaandam" type="System.String" />
<column name="ec_Type" value="XP502" type="System.String" />
<column name="ec_currency" value="EUR" type="System.String" />
</columns>
</row>
</rows>
<key>DefaultKey</key>
<total>8.82</total>
<AddOnKey>0</AddOnKey>
<data />
<parameters />
</table>
</Data>
</Data>
</Root>
So far I've tried this query:
DECLARE @XMLData XML = ('<Root>
<Data>
<Data>
<table>
<id>{54bd0b6f-693e-476f-a80e-0094de4cf3b4}</id>
<rows>
<row>
<columns>
<column name="ec_date" value="27-July-2021" type="System.DateTime" />
<column name="ec_description" value="Reiskosten woon-werk" type="System.String" />
<column name="ec_Type" value="XP504" type="System.String" />
<column name="ec_currency" value="EUR" type="System.String" />
</columns>
</row>
</rows>
<key>DefaultKey</key>
<total>145.14</total>
<AddOnKey>0</AddOnKey>
<data />
<parameters />
</table>
</Data>
</Data>
<Data>
<Data>
<table>
<id>{9adfe4dd-49be-48fb-a838-009e861be8bd}</id>
<rows>
<row>
<columns>
<column name="ec_date" value="24-August-2021" type="System.DateTime" />
<column name="ec_description" value="reiskosten Alkmaar-ZaandamXP502" type="System.String" />
<column name="ec_Type" value="XP502" type="System.String" />
<column name="ec_currency" value="EUR" type="System.String" />
</columns>
</row>
<row>
<columns>
<column name="ec_date" value="26-August-2021" type="System.DateTime" />
<column name="ec_description" value="reiskosten Alkmaar-Zaandam" type="System.String" />
<column name="ec_Type" value="XP502" type="System.String" />
<column name="ec_currency" value="EUR" type="System.String" />
</columns>
</row>
</rows>
<key>DefaultKey</key>
<total>8.82</total>
<AddOnKey>0</AddOnKey>
<data />
<parameters />
</table>
</Data>
</Data>
</Root>')
SELECT top 2000
ID = id.value('(table/id)[1]', 'nvarchar(255)'),
ec_date = ColumnData.value('Column[1]', 'nvarchar(255)')
ec_description = ColumnData.value('Column[2]', 'nvarchar(255)')
FROM
@XMLData.nodes('/Root/Data/Data') AS XTbl(id)
CROSS APPLY
id.nodes('table/rows/row/columns') AS XTbl2(ColumnData)
The result is like this: | ID | ec_date | ec_description | | -------- | -------- | -------- | | 54bd0b6f-693e-476f-a80e-0094de4cf3b4 | NULL | NULL | | 9adfe4dd-49be-48fb-a838-009e861be8bd | NULL | NULL | | 9adfe4dd-49be-48fb-a838-009e861be8bd | NULL | NULL |
when there are multiple rows linked to an ID it correctly makes multiple rows.
The problem I'm having is that I can't seem to get the value from the XML columns.
Please try the following solution.
It will will work starting from SQL Server 2017 onwards.
Notable points:
OUTER APPLY
simulates parent/child relationship between two levels in the input XML..nodes()
method XPath expressions were properly adjusted.TRIM(...)
function is used to remove curly brackets. That function was introduced in SQL Server 2017.SQL
DECLARE @XMLData XML =
N'<Root>
<Data>
<Data>
<table>
<id>{54bd0b6f-693e-476f-a80e-0094de4cf3b4}</id>
<rows>
<row>
<columns>
<column name="ec_date" value="27-July-2021"
type="System.DateTime"/>
<column name="ec_description"
value="Reiskosten woon-werk"
type="System.String"/>
<column name="ec_Type" value="XP504"
type="System.String"/>
<column name="ec_currency" value="EUR"
type="System.String"/>
</columns>
</row>
</rows>
<key>DefaultKey</key>
<total>145.14</total>
<AddOnKey>0</AddOnKey>
<data/>
<parameters/>
</table>
</Data>
</Data>
<Data>
<Data>
<table>
<id>{9adfe4dd-49be-48fb-a838-009e861be8bd}</id>
<rows>
<row>
<columns>
<column name="ec_date" value="24-August-2021"
type="System.DateTime"/>
<column name="ec_description"
value="reiskosten Alkmaar-ZaandamXP502"
type="System.String"/>
<column name="ec_Type" value="XP502"
type="System.String"/>
<column name="ec_currency" value="EUR"
type="System.String"/>
</columns>
</row>
<row>
<columns>
<column name="ec_date" value="26-August-2021"
type="System.DateTime"/>
<column name="ec_description"
value="reiskosten Alkmaar-Zaandam"
type="System.String"/>
<column name="ec_Type" value="XP502"
type="System.String"/>
<column name="ec_currency" value="EUR"
type="System.String"/>
</columns>
</row>
</rows>
<key>DefaultKey</key>
<total>8.82</total>
<AddOnKey>0</AddOnKey>
<data/>
<parameters/>
</table>
</Data>
</Data>
</Root>';
SELECT TRIM('{}' FROM p.value('(id/text())[1]', 'NVARCHAR(255)')) AS ID
, c.value('(column[@name="ec_date"]/@value)[1]', 'NVARCHAR(255)') AS ec_date
, c.value('(column[@name="ec_description"]/@value)[1]', 'NVARCHAR(255)') AS ec_description
, c.value('(column[@name="ec_Type"]/@value)[1]', 'NVARCHAR(255)') AS ec_Type
, c.value('(column[@name="ec_currency"]/@value)[1]', 'CHAR(3)') AS ec_currency
FROM @XMLData.nodes('/Root/Data/Data/table') AS t1(p)
OUTER APPLY p.nodes('rows/row/columns') AS t2(c);
Output
+--------------------------------------+----------------+---------------------------------+---------+-------------+
| ID | ec_date | ec_description | ec_Type | ec_currency |
+--------------------------------------+----------------+---------------------------------+---------+-------------+
| 54bd0b6f-693e-476f-a80e-0094de4cf3b4 | 27-July-2021 | Reiskosten woon-werk | XP504 | EUR |
| 9adfe4dd-49be-48fb-a838-009e861be8bd | 24-August-2021 | reiskosten Alkmaar-ZaandamXP502 | XP502 | EUR |
| 9adfe4dd-49be-48fb-a838-009e861be8bd | 26-August-2021 | reiskosten Alkmaar-Zaandam | XP502 | EUR |
+--------------------------------------+----------------+---------------------------------+---------+-------------+