How to update multiple SQL records, with merge with multiple options, based on an XML document?



I'm relatively new to SQL (a week or so), and I have a bunch of xml files that have a structure somewhat like this:



<foods>
<type>
<food_id>123456789</food_id>
<food_type>bacon</food_type>
<food_information>
<stuff>blah</stuff>
</food_information>
<more_food_info>
<more_stuff>blah</more_stuff>
</more_food_info>
</type>
<type>
<food_id>123456780</food_id>
<food_type>eggs</food>
<food_information>
<stuff>blahblah</stuff>
</food_information>
<more_food_info>
<more_stuff>blahblahblah</more_stuff>
</more_food_info>
</type>
</foods>


I am doing Bulk inserts via SQL. Now, this database contains tens of millions of records of food. Almost everything is unique, but the one unique value is the "food_id" value. It is always unique. However, newer XML files contain updates for the old records, and I need to be able to use ONLY those new records, not the old ones.


food_information is a table containing a bunch of stuff.


more_food_info is also another table containing a bunch of stuff.


Everything has the proper primary and foreign key relationship set up. The main table has a primary key of Type_ID. The sub-tables have a primary key of Name_ID without (e.g.: FoodInformation_ID).


My insertion code also works perfectly:



DECLARE @xml_data xml
DECLARE @xdoc INT

SET @xml_data = (SELECT CONVERT(xml, BulkColumn, 2) FROM OPENROWSET(Bulk 'foods.xml', SINGLE_CLOB) [rowresults])

EXEC sp_xml_preparedocument @xdoc, OUTPUT, @xml_data

INSERT INTO [type]
SELECT * FROM OPENXML(@xdoc, '/foods/type', 2)
WITH
(
[food_id] VARCHAR(8) 'food_id',
[food_type] VARCHAR(255) 'food_type',
)

INSERT INTO [food_information]
SELECT
[type].[Type_ID],
xml.[stuff] FROM [type]
INNER JOIN OPENXML(@xdoc, '/foods/type', 2)
WITH
(
[food_id] VARCHAR(8) '../food_id',
[stuff] VARCHAR(255) 'stuff'
)
AS XML ON xml.[food_id] = [type].[food_id]
-- Repeat the same style for every other table... (not the same as the [type] table)

EXEC sp_xml_removedocument


This works 100%, but I need to be able to match everything from these foreign keys to the primary key, and, of course, to the serial number, to update all records based on it. I don't know how to do this for multiple records.


I need all tables joined in a MERGE update, but I only know how to merge the FIRST table since I can't seem to insert other conditions from other tables. Or I need a way to find all records relating to that food_id and delete the lowest Type_ID number (primary key) for each record and match that to the corresponding foreign key to delete the other records in the other tables.


The problem is that food_id when reading bulk xml returns a giant list of ids. I only want the one we're currently on, so I can't compare it. And "IN (select statement)" is not what I'm looking for: it has to be one at a time.


TLDR: How do I do this? psuedo-code:



Read XML document.
If exists (SELECT [food_id] from [type] WHERE [food_id] = current_xml_food_id)
THEN
-- Update/MERGE stuff
-- Include all the other tables that need updating:
-- ... food_information, more_food_info, etc.
-- ...and make sure the foreign key relationship stays
-- ...intact. We need to match Type_ID (main table
-- ...PrimaryKey) to TableName_ID (ForeignKey)
ELSE
-- Insert stuff
End read

No comments:

Post a Comment