Search code examples
sql-serverxmldatabasestored-procedurescursor

Have to map XML data into a SQL table?


I'm getting XML data in my stored procedure and want to update the corresponding SQL Server table by mapping the values.

This is a sample of the XML:

DECLARE @xmlData XML = '<NewDataSet>
      <Table>
        <SystemKey>India</SystemKey>
        <Translation>Bharat</Translation>
      </Table>
      <Table>
        <SystemKey>UAE</SystemKey>
        <Translation>United Arab Emirates</Translation>
      </Table>
      <Table>
        <SystemKey>Afghanistan</SystemKey>
        <Translation>Afghanistan</Translation>
      </Table>
      </NewDataSet>'

Code is as follows:

SELECT 
    t.c.value('(SystemKey/text())[1]', 'NVARCHAR(MAX)') AS [SystemKey],
    r.c.value('text()[1]', 'NVARCHAR(MAX)') AS Translation
FROM 
    @xmldata.nodes('NewDataSet/Table') AS t(c)
CROSS APPLY 
    t.c.nodes('*[local-name(.) != "SystemKey"]') AS r(c)

I want to update table 2 with the values from XML data; eg. SystemKey = Table2.KEY AND Translation = Table2.Translation.

Can I do this directly without a temp table and a cursor?


Solution

  • Is this what you're after? (I wasn't sure what type of update you were trying to achieve. You could do the same with a merge if you want an insert or update).

    DECLARE @xmlData XML = '<NewDataSet>
          <Table>
            <SystemKey>India</SystemKey>
            <Translation>Bharat</Translation>
          </Table>
          <Table>
            <SystemKey>UAE</SystemKey>
            <Translation>United Arab Emirates</Translation>
          </Table>
          <Table>
            <SystemKey>Afghanistan</SystemKey>
            <Translation>Afghanistan</Translation>
          </Table>
          </NewDataSet>';
    
    WITH Translations
    AS
    (
        SELECT 
            t.c.value('(SystemKey/text())[1]', 'NVARCHAR(MAX)') AS [SystemKey],
            r.c.value('text()[1]', 'NVARCHAR(MAX)') AS Translation
        FROM 
            @xmldata.nodes('NewDataSet/Table') AS t(c)
        CROSS APPLY 
            t.c.nodes('*[local-name(.) != "SystemKey"]') AS r(c)
    )
    UPDATE t2 
        SET t2.Translation = t.Translation 
    FROM Table2 AS t2
    INNER JOIN Translations AS t
    ON t.SystemKey = t2.SystemKey;