あなたは正しい軌道に乗っています。XML を使用して、オンライン ポータルとクライアント/サーバー アプリケーションの間でデータを転送する同様のセットアップがあります。セットアップの残りの部分は、あなたが持っているものと非常に似ています。
一時テーブルにインデックスを付ける方法に関係なく、PK フィールドではないフィールドを比較する場合、テーブルにインデックスが付けられていないという事実は少し心配です。マージ一致句で使用されるすべてのフィールドを含む 1 つのインデックス、またはそれらのそれぞれのインデックスを使用することが重要です。前者の方がパフォーマンスが優れていることがわかりました。さらに、XML パラメーターを使用して、OpenXML と一時テーブルを使用する方法があります。
次のコードはテストされていないため、多少のデバッグが必要になる場合がありますが、正しい軌道に乗せることができます。いくつかの注意事項: OpenXML WITH 句のすべてのフィールドが属性の場合、最後のパラメーター (つまり、", 2") とフィールド ソース指定子 (つまり、詳細テーブルの "@id") を削除できます。説明のデータはフラットですが、その場合、必要なテーブルは 1 つだけですが、リンクされたレコードにインポートする必要があることがよくあります。完全を期すために、単純な主従関係の例を以下のコードに含めました。
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