I have a list of data that I am passing to a stored procedure as XML. The data is a list of Widget
and a widget contains a list of WidgetItem
(parent child data). I would like to do a MERGE
based a subset of Widget
based on the ParentID
. Some data for the ParentID
has been updated, some has been removed (so missing from the xml) and some data is new.
The updated data will never need the child data updated as the Widget
record can only be adjusted, not the items (child data) inside it. Insert will always have a one or more child records (WidgetItems).
I can't seem to figure out how to do this in a MERGE
as that seems like the best approach as compared to handling the merge in the data layer.
Here is what I have so far... I put a comments where I am stuck:
CREATE PROCEDURE dbo.pWidgetsMerge
@Widgets XML
AS
/*
Assumed XML input @Widgets xml:
<Widgets>
<Widget>
<WidgetID>
<ParentID>
<StartDate>
<EndDate>
<Details>
<WidgetDetailItem>
<WidgetDetailItemID>
<WidgetID>
<SomeID>
<SomeData>
*/
MERGE
[dbo].[Widget] as w
USING
(
SELECT
'WidgetID' = P.value('WidgetID[1]', 'INT'),
'ParentID' = P.value('ParentID[1]', 'INT'),
'StartDate' = P.value('EffectiveStartDate[1]', 'DATETIME'),
'EndDate' = P.value('EffectiveEndDate[1]', 'DATETIME')
FROM
@Widgets.nodes('/Widgets/Widget') PROPERTYFEED(P)
)
AS xmlIn
(
[WidgetID],
[StartDate],
[EndDate]
)
ON
w.[WidgetID] = xmlIn.[WidgetID]
WHEN
NOT MATCHED
THEN
INSERT
(
[ParentID],
[StartDate],
[EndDate]
)
VALUES
(
xmlIn.[ParentID],
xmlIn.[StartDate],
xmlIn.[EndDate]
)
/*STUCK HERE: After the insert, need to put in the child
records into a new table [WidgetItems]. Maybe it's another
operation outside of the merge?*/
WHEN
MATCHED AND (
(w.[StartDate] <> xmlIn.[StartDate]) OR
(w.[EndDate] <> xmlIn.[EndDate]))
THEN
UPDATE SET
w.[StartDate] = xmlIn.[StartDate],
w.[EndDate] = xmlIn.[EndDate]
WHEN
NOT MATCHED BY SOURCE AND w.[ParentID] = xmlIn.[ParentID]
THEN
UPDATE SET
w.[DeletedDate] = GETDATE()
Also, if I am approaching this wrong an alternative solution would be appreciated or maybe I do need to handle this at the data layer.