简体   繁体   中英

SQL Server XML query values to columns

I'm trying to shred a table of XML documents into SQL Server columns and am going around in circles with one bit.

Basically I have a table ( ID int, XMLData XML ) and each row will contain a document in the XML column.

I need to turn it into the following format

(
ID int, 
ReferenceCurrency varchar, 
TargetCurrency varchar, 
ReferenceAmount decimal, 
TargetAmount decimal, 
DueDate date
)

I've cut down this table.

The code I have inherited was a mix of XML.value and string searches with charindex which haven't been too reliable.

This is a snippet of the message we have.

<ReferenceCurrency>
      <Ccy>GBP</Ccy>
</ReferenceCurrency>
<TargetCurrency>
      <Ccy>USD</Ccy>
</TargetCurrency>    
<BalanceAmtItem Type="technical_account_settlement_balance_due_to_sender">
      <Amt Ccy="USD" CcyIndic="reference_currency" Share="receiver_share">65.62</Amt>
      <Amt Ccy="USD" CcyIndic="target_currency" Share="receiver_share">96.62</Amt>
      <DueDate>2019-09-04</DueDate>
</BalanceAmtItem>

I can get most of the data just using XML.value

SELECT 
    ID, 
    XMLDATA.value('(Jv-Ins-Reinsurance/TechAccount/ReferenceCurrency)[1]', 'varchar(4)') AS ReferenceCurrency ,
    XMLDATA.value('(Jv-Ins-Reinsurance/TechAccount/TargetCurrency)[1]', 'varchar(4)') AS TargetCurrency,
    XMLDATA.value('(Jv-Ins-Reinsurance/TechAccount/BalanceAmtItem/DueDate)[1]', 'date') AS DueDate
FROM
    dta

The bit I'm struggling with is how to get the two amount columns where CcyIndic = reference_currency or target_currency.

In this example I would expect to get a single line of 1, GBP, USD, 65.62, 96.62, 2019-09-04

Any help appreciated.

Something like this:

declare @doc xml = 
'<ReferenceCurrency>
      <Ccy>GBP</Ccy>
</ReferenceCurrency>
<TargetCurrency>
      <Ccy>USD</Ccy>
</TargetCurrency>    
<BalanceAmtItem Type="technical_account_settlement_balance_due_to_sender">
      <Amt Ccy="USD" CcyIndic="reference_currency" Share="receiver_share">65.62</Amt>
      <Amt Ccy="USD" CcyIndic="target_currency" Share="receiver_share">96.62</Amt>
      <DueDate>2019-09-04</DueDate>
</BalanceAmtItem>';

SELECT 
   -- ID, 
    XMLDATA.value('(/ReferenceCurrency)[1]', 'varchar(4)') AS ReferenceCurrency,
    XMLDATA.value('(/TargetCurrency)[1]', 'varchar(4)') AS TargetCurrency,
    XMLDATA.value('(/BalanceAmtItem/Amt[@CcyIndic="reference_currency"])[1]', 'varchar(4)') AS ReferenceAmount ,
    XMLDATA.value('(/BalanceAmtItem/Amt[@CcyIndic="target_currency"])[1]', 'varchar(4)') AS TargetAmount ,
    XMLDATA.value('(/BalanceAmtItem/DueDate)[1]', 'date') AS DueDate
FROM
    (select @doc XMLDATA) d

outputs

ReferenceCurrency TargetCurrency ReferenceAmount TargetAmount DueDate
----------------- -------------- --------------- ------------ ----------
GBP               USD            65.6            96.6         2019-09-04

SQL

-- DDL and sample data population, start
DECLARE @tbl TABLE(ID INT IDENTITY(1,1) PRIMARY KEY, XMLData XML);
INSERT INTO @tbl
VALUES
(N'<Jv-Ins-Reinsurance>
    <TechAccount>
        <ReferenceCurrency>
            <Ccy>GBP</Ccy>
        </ReferenceCurrency>
        <TargetCurrency>
            <Ccy>USD</Ccy>
        </TargetCurrency>
        <BalanceAmtItem Type="technical_account_settlement_balance_due_to_sender">
            <Amt Ccy="USD" CcyIndic="reference_currency" Share="receiver_share">65.62</Amt>
            <Amt Ccy="USD" CcyIndic="target_currency" Share="receiver_share">96.62</Amt>
            <DueDate>2019-09-04</DueDate>
        </BalanceAmtItem>
    </TechAccount>
</Jv-Ins-Reinsurance>');
-- DDL and sample data population, end

SELECT ID, 
    c.value('(ReferenceCurrency/Ccy)[1]', 'varchar(4)') AS ReferenceCurrency ,
    c.value('(TargetCurrency/Ccy)[1]', 'varchar(4)') AS TargetCurrency,
    c.value('(BalanceAmtItem/Amt[@CcyIndic="reference_currency"])[1]', 'MONEY') AS ref_money,
    c.value('(BalanceAmtItem/Amt[@CcyIndic="target_currency"])[1]', 'MONEY') AS target_money,
    c.value('(BalanceAmtItem/DueDate)[1]', 'date') AS DueDate
FROM @tbl AS tbl
CROSS APPLY tbl.xmldata.nodes('/Jv-Ins-Reinsurance/TechAccount') AS t(c);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM