SQL Server XML query values to columns - sql-server

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.

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);

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

Related

How to combine two FOR XML AUTO into 1 XML?

We are using SQL Server 2012.
Table myTbl has a one to many relationship to table myAllocation
Table ABC_myTbl has a one to many relationship to table ABC_myAllocation
The below query combined 2 FOR XML AUTO into 1 XML, but the problem is ID, SystemSource, Manager are included in element TradeTicket instead of on their own, and accountManager, unitPrice are included in element allocationRow instead of on their own.
Thank you
SELECT '<?xml version="1.0"?>'+
(SELECT
( SELECT trTicket.[id],trTicket.[manager],'PFM' as SystemSource
,allocationRow.accountNumber,allocationRow.unitPrice
FROM myTbl AS trTicket
LEFT JOIN myAllocation AS allocationRow ON allocationRow.trade_ticket_id=trTicket.id
WHERE trTicket.ID = 8779631
ORDER BY trTicket.id,allocationRow.AccountNumber
FOR XML AUTO, type)
,
(
SELECT trTicket.[id],trTicket.[manager],'CRD' as SystemSource
,allocationRow.accountNumber,allocationRow.unitPrice
FROM ABC_myTbl AS trTicket
LEFT JOIN ABC_myAllocation AS allocationRow ON allocationRow.trade_ticket_id=trTicket.id
WHERE trTicket.ID = 8
ORDER BY trTicket.id,allocationRow.AccountNumber
FOR XML AUTO, type)
FOR XML PATH('trTickets'), ELEMENTS) AS XMLResult
This is the current result:
<?xml version="1.0"?>
<trTickets>
<trTicket id="8779631" SystemSource="PFM" manager="MCM">
<allocationRow accountNumber="292 " unit_Price="300"/>
</trTicket>
<trTicket id="8" SystemSource="CRD" manager="DOYLE">
<allocationRow unitPrice="100" accountNumber="F11 "/>
<allocationRow unitPrice="200" accountNumber="F22 "/>
</trTicket>
</trTickets>
This is the desired result that I am looking for:
<?xml version="1.0"?>
<trTickets>
<trTicket>
<id>8</id>
<manager>DOYLE</manager>
<SystemSource>CRD</SystemSource>
<allocationRow>
<accountNumber>F11</accountNumber>
<unitPrice>100</unitPrice>
</allocationRow>
<allocationRow>
<accountNumber>F22</accountNumber>
<unitPrice>200</unitPrice>
</allocationRow>
</trTicket>
<trTicket>
<id>8779631</id>
<manager>MCM</manager>
<SystemSource>PFM</SystemSource>
<allocationRow>
<accountNumber>292</accountNumber>
<unitPrice>300</unitPrice>
</allocationRow>
</trTicket>
</trTickets>
Data sample:
Table ABC_myTbl:
ID Manager
-----------
8 DOYLE
Table ABC_myAllocation:
accountNumber unitPrice
-------------------------
F11 100
F22 200
Table myTbl:
ID Manager
---------------
8779631 MCM
Table myAllocation:
accountNumber unitPrice
--------------------------
292 300
DDL for the tables and their data:
CREATE TABLE dbo.ABC_myTbl
(
ID INT NOT NULL,
MANAGER VARCHAR(10) NOT NULL
)
CREATE TABLE dbo.myTbl
(
ID INT NOT NULL,
MANAGER VARCHAR(10) NOT NULL
)
CREATE TABLE dbo.ABC_myAllocation
(
accountNumber VARCHAR(10) NOT NULL,
unitprice NUMERIC(10, 3) NOT NULL
)
CREATE TABLE dbo.myAllocation
(
accountNumber VARCHAR(10) NOT NULL,
unitprice NUMERIC(10, 3) NOT NULL
)
INSERT INTO dbo.ABC_myTbl VALUES (8,'DOYLE')
INSERT INTO dbo.ABC_myAllocation VALUES ('F11',100)
INSERT INTO dbo.ABC_myAllocation VALUES ('F22',200)
INSERT INTO dbo.myTbl VALUES (8779631,'MCM')
INSERT INTO dbo.myAllocation VALUES ('292',300)
I didn't wait for your DDL and sample data population. So I created a conceptual sample for you. Please pay attention that the tables have implied relationships and they are used in the WHERE clauses.
SQL
-- DDL and sample data population, start
DECLARE #tbl1 TABLE (ID INT PRIMARY KEY, Manager VARCHAR(20));
INSERT INTO #tbl1 (ID, Manager) VALUES
(8, 'DOYLE'),
(9, 'XYZ');
DECLARE #tbl1Child TABLE (accountNumber CHAR(3) PRIMARY KEY, ParentID INT, unitPrice DECIMAL(10,2));
INSERT INTO #tbl1Child (accountNumber, ParentID, unitPrice) VALUES
('F11', 8, 100)
,('F22', 8, 200)
,('F70', 9, 770);
DECLARE #tbl2 TABLE (ID INT PRIMARY KEY, Manager VARCHAR(20));
INSERT INTO #tbl2 (ID, Manager) VALUES
(8779631, 'MCM')
,(8779555, 'TTT');
DECLARE #tbl2Child TABLE (accountNumber CHAR(3) PRIMARY KEY, ParentID INT, unitPrice DECIMAL(10,2));
INSERT INTO #tbl2Child (accountNumber, ParentID, unitPrice) VALUES
('292', 8779631, 300)
,('255', 8779555, 500);
-- DDL and sample data population, end
SELECT TOP(1) NULL
, (
SELECT *
, (
SELECT * FROM #tbl1Child AS c
WHERE p.ID = c.ParentID
FOR XML PATH('allocation_row'), TYPE
)
FROM #tbl1 AS p
FOR XML PATH('tradeTicket'), TYPE
)
, (
SELECT *
, (
SELECT * FROM #tbl2Child AS c
WHERE p.ID = c.ParentID
FOR XML PATH('allocation_row'), TYPE
)
FROM #tbl2 AS p
FOR XML PATH('tradeTicket'), TYPE
)
FROM #tbl1
FOR XML PATH(''), TYPE, ROOT('tradeTickets');
Output
<tradeTickets>
<tradeTicket>
<ID>8</ID>
<Manager>DOYLE</Manager>
<allocation_row>
<accountNumber>F11</accountNumber>
<ParentID>8</ParentID>
<unitPrice>100.00</unitPrice>
</allocation_row>
<allocation_row>
<accountNumber>F22</accountNumber>
<ParentID>8</ParentID>
<unitPrice>200.00</unitPrice>
</allocation_row>
</tradeTicket>
<tradeTicket>
<ID>9</ID>
<Manager>XYZ</Manager>
<allocation_row>
<accountNumber>F70</accountNumber>
<ParentID>9</ParentID>
<unitPrice>770.00</unitPrice>
</allocation_row>
</tradeTicket>
<tradeTicket>
<ID>8779555</ID>
<Manager>TTT</Manager>
<allocation_row>
<accountNumber>255</accountNumber>
<ParentID>8779555</ParentID>
<unitPrice>500.00</unitPrice>
</allocation_row>
</tradeTicket>
<tradeTicket>
<ID>8779631</ID>
<Manager>MCM</Manager>
<allocation_row>
<accountNumber>292</accountNumber>
<ParentID>8779631</ParentID>
<unitPrice>300.00</unitPrice>
</allocation_row>
</tradeTicket>
</tradeTickets>

How to get an xml attribute value from a table's column in a select list

DECLARE #xml AS XML
SET #xml = CONVERT(xml,'<data><UserType userID="123">employee</UserType></data>')
SELECT (SELECT d.value('#userID', 'int')
FROM #xml.nodes('//data/UserType') T(d))
I have a table where the column is like the XML above. Is it possible to get the #userID value in a select statement?
In my Users table, the column 'XmlData' is of type XML.
SELECT
userID -- u.XmlData
FROM Users u
How can I grab the userID attribute from the xml in a select statement? I know how to parse it once, but not in a select.
You knit those together with APPLY. Something like:
SELECT
u.*,
SELECT T.d.value('#userID', 'int') userID
FROM Users u
CROSS APPLY u.XmlData.nodes('/data/UserType') T(d)
Same idea like John Cappelletti, just with CTE for conversion to XML.
SQL
DECLARE #tbl TABLE (ID INT IDENTITY PRIMARY KEY, XMLData NVARCHAR(MAX));
INSERT INTO #tbl (XMLData)
VALUES
(N'<data><UserType userID="123">employee</UserType></data>');
;WITH rs AS
(
SELECT *, TRY_CAST(XMLData AS XML) AS xml_data FROM #tbl
)
SELECT ID
, col.value('#userID','INT') AS userID
FROM rs
CROSS APPLY rs.[xml_Data].nodes('/data/UserType') AS tab(col);
Output
+----+--------+
| ID | userID |
+----+--------+
| 1 | 123 |
+----+--------+
With a little twist.
Example
Declare #YourTable table (ID int,XMLData nvarchar(max))
Insert Into #YourTable values
(1,'<data><UserType userID="123">employee</UserType></data>')
Select A.ID
,C.*
From #YourTable A
Cross Apply ( values (convert(XML,XMLData) )) B(XData)
Cross Apply ( Select UserID = d.value('#userID', 'int')
From XData.nodes('/data/UserType') T(d)
) C
Returns
ID UserID
1 123
Update If only ONE User ID in the XML
Declare #YourTable table (ID int,XMLData nvarchar(max))
Insert Into #YourTable values
(1,'<data><UserType userID="123">employee</UserType></data>')
Select A.ID
,UserID = convert(XML,XMLData).value('/data[1]/UserType[1]/#userID', 'int')
From #YourTable A

Query (SQL Server) to get value from node in XML column stored as varchar(max)?

I hate dealing with XML queries. I don't do it often enough to remember how to format everything, but I'm at my wits' end.
Let's say I have a table called Messages and a column inside it called Payload. Payload contains XML stored as varchar(max). The XML is formatted as such:
<NCOAPACP xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="uri://www.gen.da.hob/VC/Contract/QualityManagement/EMSM">
<VID>3656183</VID>
</NCOAPACP>
How do I query the table to retrieve a list of the values in the VID node?
Try this:
declare #w as xml = cast('
<NCOAPACP xmlns:i=''http://www.w3.org/2001/XMLSchema-instance''
xmlns="uri://www.gen.da.hob/VC/Contract/QualityManagement/EMSM">
<VID>3656183</VID>
</NCOAPACP>' as xml)
SELECT #w.value('declare namespace ns="uri://www.gen.da.hob/VC/Contract/QualityManagement/EMSM";
ns:NCOAPACP[1]/ns:VID[1]','varchar(10)') AS VID
If you have multiple VID node you can try this:
declare #w as xml = cast('
<NCOAPACP xmlns:i=''http://www.w3.org/2001/XMLSchema-instance''
xmlns="uri://www.gen.da.hob/VC/Contract/QualityManagement/EMSM">
<VID>3656183</VID>
<VID>454545</VID>
</NCOAPACP>' as xml)
SELECT VID.value('.','varchar(10)')
from #w.nodes(
'declare namespace ns="uri://www.gen.da.hob/VC/Contract/QualityManagement/EMSM";
ns:NCOAPACP[1]/ns:VID'
)
AS C(VID)
If XML data are in a table column then the solution is a little more tricky. Especially if data type is varchar(max).
declare #tbl table(id int,payload varchar(max))--sample table
--sample data
insert #tbl values
(1,'<NCOAPACP xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="uri://www.gen.da.hob/VC/Contract/QualityManagement/EMSM">
<VID>3656183</VID>
<VID>3656184</VID>
</NCOAPACP>'),
(2,'<NCOAPACP xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="uri://www.gen.da.hob/VC/Contract/QualityManagement/EMSM">
<VID>123456</VID>
<VID>987654</VID>
</NCOAPACP>')
--it is convenient to define namespaces before the query
;with xmlnamespaces('uri://www.gen.da.hob/VC/Contract/QualityManagement/EMSM' as x)--we will use this x:
select id, t.vid.value('.[1]','varchar(20)') vid
-- . means self. [1] ensure single value
from
--convert varchar(max) to xml first
(select id,cast(payload as xml) payload from #tbl) tt
cross apply
--convert xml to a tabular form
tt.payload.nodes('//x:VID') t(vid)
Results:
id vid
1 3656183
1 3656184
2 123456
2 987654
U can try this
DECLARE #Messages TABLE(ID INT, Payload NVARCHAR(MAX))
INSERT INTO #Messages(ID, Payload) VALUES(1, '<NCOAPACP xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="uri://www.gen.da.hob/VC/Contract/QualityManagement/EMSM"> <VID>3656183</VID> </NCOAPACP>')
INSERT INTO #Messages(ID, Payload) VALUES(2, '<NCOAPACP xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="uri://www.gen.da.hob/VC/Contract/QualityManagement/EMSM"> <VID>3656183</VID> <VID>3656184</VID> </NCOAPACP>')
;WITH CTE(ID, Payload) AS
(
SELECT ID, CAST(Payload AS XML)
FROM #Messages
)
SELECT
ID,
x.items.value('.', 'NVARCHAR(10)')
FROM CTE
CROSS APPLY Payload.nodes('declare namespace xx="uri://www.gen.da.hob/VC/Contract/QualityManagement/EMSM"; xx:NCOAPACP/xx:VID') as x(items)
The most simple way (CTE test created just to get output, your xml value converted to varchar(max) as in your table, then SELECT *.value):
;WITH test AS (
SELECT CAST(
'<NCOAPACP xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="uri://www.gen.da.hob/VC/Contract/QualityManagement/EMSM">
<VID>3656183</VID>
</NCOAPACP>' as varchar(max)) as Payload
)
SELECT CAST(Payload as xml).value('(/*/*)[1]', 'int')
FROM test
Output:
3656183

SQL Query to Append Past Order with Most Recent Order

I have an order table that has both past membership data and current data. I want to view this data in single row. I have a temp table for past data, but not exactly sure how to write this query to get current data in the same row. I know it has something to do with the MAX(order no). Here is the query to get the past membership data in a temp table
set transaction isolation level read uncommitted
declare
#ship_master_customer_id varchar (10), #cycle_begin_date datetime, #cycle_end_date datetime, #OrderNo varchar(10), #Description Char(100)
create table #t1(ShipMasterCustomerID varchar(10), OrderNo varchar (10), cycle_begin_date datetime, cycle_end_date datetime, Description Char(100))
Insert into #t1
Select SHIP_MASTER_CUSTOMER_ID, ORDER_NO, CYCLE_BEGIN_DATE,CYCLE_END_DATE, DESCRIPTION FROM [ORDER_DETAIL]
where SHIP_MASTER_CUSTOMER_ID = '11115555' and
CYCLE_END_DATE = '2/29/2016'
Select * from #t1
Drop table #t1
Here is my script.
declare
#ship_master_customer_id varchar (10), #cycle_begin_date datetime, #cycle_end_date datetime, #OrderNo varchar(10), #Description Char(100)
create table #t2(ShipMasterCustomerID varchar(10), OrderNo varchar (10), cycle_begin_date datetime, cycle_end_date datetime, Description Char(100))
Insert into #t2 (shipmastercustomerid, orderno, cycle_begin_date, cycle_end_date, DESCRIPTION)
VALUES (1111555,9004731815, 2015/01/01, 2015/31/12,'Annual Mem'),
(1111555, 9005148308, 2016/01/01, 2016/31/12,'Annual Mem'),
(1111222, 9005027152, 2015/01/03, 2016/29/02,'Annual Mem'),
(1111222, 9005440369, 2016/01/03, 2017/31/03,'Annual Mem'),
(2223333, 9005027152, 2014/01/01, 2016/31/12,'Annual Mem'),
(2223333, 9005442116, 2016/01/01, 2017/31/12,'Annual Mem')
Select * from #t2
Drop table #t2
Sample Data
You don't need a temp table. You can query the same table twice, giving it an alias and then use the alias to prefix your column names. Since you didn't give us a complete schema or a fiddle I'm simulating your database with a temp table but the essence is here. There are considerations that you didn't mention, though. Are you guaranteed that every customer will have both a historical AND a current record? If not, they will not appear in the query below because of the INNER JOIN. You could change it to an OUTER join but when customers don't have a new record you will see NULL values in those columns. My point is that here be dragons... this is by no means a complete or bulletproof solution, only a nudge in the right direction.
DECLARE #ORDER_DETAIL AS TABLE(
ShipMasterCustomerId varchar(20),
OrderNo varchar(20),
cycle_begin_date date,
cycle_end_date date,
Description varchar(100)
)
INSERT #ORDER_DETAIL SELECT '11115555', '9005337015', '02/26/15', '2/29/16', 'Membership 26-Feb-2015 to 29-Feb-2016'
INSERT #ORDER_DETAIL SELECT '11115555', '9005743023', '02/28/17', '2/28/17', 'Membership 01-Mar-2016 to 28-Feb-2017'
SELECT
hist.ShipMasterCustomerId,
hist.OrderNo,
hist.cycle_begin_date,
hist.CYCLE_END_DATE,
hist.[Description],
curr.ShipMasterCustomerId,
curr.OrderNo,
curr.cycle_begin_date,
curr.CYCLE_END_DATE,
curr.[Description]
FROM
#ORDER_DETAIL AS hist
INNER JOIN #ORDER_DETAIL AS curr ON (
(curr.ShipMasterCustomerId = hist.ShipMasterCustomerId) AND (curr.cycle_end_date =
(SELECT MAX(cycle_end_date) FROM #ORDER_DETAIL WHERE ShipMasterCustomerId = hist.ShipMasterCustomerId))
)
WHERE
(hist.ShipMasterCustomerId = '11115555')
AND
(hist.cycle_end_date = '2/29/2016')

Insert from single table into multiple tables, invalid column name error

I am trying to do the following but getting an "Invalid Column Name {column}" error. Can someone please help me see the error of my ways? We recently split a transaction table into 2 tables, one containing the often updated report column names and the other containing the unchanging transactions. This leave me trying to change what was a simple insert into 1 table to a complex insert into 2 tables with unique columns. I attempted to do that like so:
INSERT INTO dbo.ReportColumns
(
FullName
,Type
,Classification
)
OUTPUT INSERTED.Date, INSERTED.Amount, INSERTED.Id INTO dbo.Transactions
SELECT
[Date]
,Amount
,FullName
,Type
,Classification
FROM {multiple tables}
The "INSERTED.Date, INSERTED.Amount" are the source of the errors, with or without the "INSERTED." in front.
-----------------UPDATE------------------
Aaron was correct and it was impossible to manage with an insert but I was able to vastly improve the functionality of the insert and add some other business rules with the Merge functionality. My final solution resembles the following:
DECLARE #TransactionsTemp TABLE
(
[Date] DATE NOT NULL,
Amount MONEY NOT NULL,
ReportColumnsId INT NOT NULL
)
MERGE INTO dbo.ReportColumns AS Trgt
USING ( SELECT
{FK}
,[Date]
,Amount
,FullName
,Type
,Classification
FROM {multiple tables}) AS Src
ON Src.{FK} = Trgt.{FK}
WHEN MATCHED THEN
UPDATE SET
Trgt.FullName = Src.FullName,
Trgt.Type= Src.Type,
Trgt.Classification = Src.Classification
WHEN NOT MATCHED BY TARGET THEN
INSERT
(
FullName,
Type,
Classification
)
VALUES
(
Src.FullName,
Src.Type,
Src.Classification
)
OUTPUT Src.[Date], Src.Amount, INSERTED.Id INTO #TransactionsTemp;
MERGE INTO dbo.FinancialReport AS Trgt
USING (SELECT
[Date] ,
Amount ,
ReportColumnsId
FROM #TransactionsTemp) AS Src
ON Src.[Date] = Trgt.[Date] AND Src.ReportColumnsId = Trgt.ReportColumnsId
WHEN NOT MATCHED BY TARGET And Src.Amount <> 0 THEN
INSERT
(
[Date],
Amount,
ReportColumnsId
)
VALUES
(
Src.[Date],
Src.Amount,
Src.ReportColumnsId
)
WHEN MATCHED And Src.Amount <> 0 THEN
UPDATE SET Trgt.Amount = Src.Amount
WHEN MATCHED And Src.Amount = 0 THEN
DELETE;
Hope that helps someone else in the future. :)
Output clause will return values you are inserting into a table, you need multiple inserts, you can try something like following
declare #staging table (datecolumn date, amount decimal(18,2),
fullname varchar(50), type varchar(10),
Classification varchar(255));
INSERT INTO #staging
SELECT
[Date]
,Amount
,FullName
,Type
,Classification
FROM {multiple tables}
Declare #temp table (id int, fullname varchar(50), type varchar(10));
INSERT INTO dbo.ReportColumns
(
FullName
,Type
,Classification
)
OUTPUT INSERTED.id, INSERTED.fullname, INSERTED.type INTO #temp
SELECT
FullName
,Type
,Classification
FROM #stage
INSERT into dbo.transacrions (id, date, amount)
select t.id, s.datecolumn, s.amount from #temp t
inner join #stage s on t.fullname = s.fullname and t.type = s.type
I am fairly certain you will need to have two inserts (or create a view and use an instead of insert trigger). You can only use the OUTPUT clause to send variables or actual inserted values ti another table. You can't use it to split up a select into two destination tables during an insert.
If you provide more information (like how the table has been split up and how the rows are related) we can probably provide a more specific answer.

Resources