你在正确的轨道上。我有一个类似的设置,使用 XML 在在线门户和客户端-服务器应用程序之间传输数据。其余的设置与您所拥有的非常相似。
如果您正在比较任何不是 PK 字段的字段,无论您如何索引临时表,您的表没有被索引的事实有点令人担忧。重要的是有一个索引包含合并匹配子句中使用的所有字段,或者每个索引都有一个索引 - 我发现前者会产生更好的性能。除此之外,还可以使用 XML 参数、OpenXML 和临时表。
以下代码尚未经过测试,因此可能需要进行一些调试,但它会让您走上正轨。几点注意事项:如果 OpenXML WITH 子句中的所有字段都是属性,那么您可以删除最后一个参数(即“, 2”)和字段源说明符(即详细表的“@id”)。尽管您描述中的数据是扁平的,在这种情况下您只需要一张表,但我确实经常需要导入链接记录。为了完整起见,我在下面的代码中包含了一个简单的主从关系示例。
CREATE PROCEDURE usp_ImportFromXML (@data XML) AS
BEGIN
/*
<root>
<data>
<match_field_1>1</match_field_1>
<match_field_2>val2</match_field_2>
<data_1>val3</data_1>
<data_2>val4</data_2>
<detail_records>
<detail_data id="detailID1">
<detail_1>blah1<detail_1>
<detail_2>blah2<detail_2>
</detail_data>
<detail_data id="detailID2">
<detail_1>blah3<detail_1>
<detail_2>blah4<detail_2>
</detail_data>
</detail_records>
</data>
<data>
...
</root>
*/
DECLARE @iDoc INT
EXEC sp_xml_preparedocument @iDoc OUTPUT, @data
SELECT * INTO #temp
FROM OpenXML(@iDoc, '/root/data', 2) WITH (
match_field_1 INT,
match_field_2 VARCHAR(50),
data_1 VARCHAR(50),
data_2 VARCHAR(50)
)
SELECT * INTO #detail
FROM OpenXML(@iDoc, '/root/data/detail_data', 2) WITH (
match_field_1 INT '../../match_field_1',
match_field_2 VARCHAR(50) '../../match_field_2',
detail_id VARCHAR(50) '@id',
detail_1 VARCHAR(50),
detail_2 VARCHAR(50)
)
EXEC sp_xml_removedocument @iDoc
CREATE INDEX #IX_temp ON #temp(match_field_1, match_field_2)
CREATE INDEX #IX_detail ON #detail(match_field_1, match_field_2, detail_id)
MERGE data_table a
USING #temp ta
ON ta.match_field_1 = a.match_field_1 AND ta.match_field_2 = a.match_field_2
WHEN MATCHED THEN
UPDATE SET data_1 = ta.data_1, data_2 = ta.data_2
WHEN NOT MATCHED THEN
INSERT (match_field_1, match_field_2, data_1, data_2) VALUES (ta.match_field_1, ta.match_field_2, ta.data_1, ta.data_2)
MERGE detail_table a
USING (SELECT d.*, p._key FROM #detail d, data_table p WHERE d.match_field_1 = p.match_field_1 AND d.match_field_2 = p.match_field_2) ta
ON a.id = ta.id AND a.parent_key = ta._key
WHEN MATCHED THEN
UPDATE SET detail_1 = ta.detail_1, detail2 = ta.detail_2
WHEN NOT MATCHED THEN
INSERT (parent_key, id, detail_1, detail_2) VALUES (ta._key, ta.id, ta.detail_1, ta.detail_2)
DROP TABLE #temp
DROP TABLE #detail
END