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.