この XML はそのままでは、正しく解析できません。それを変更する必要があります - 各項目とそのitemid
サブ項目を別のノードに配置する必要があります。そうしないと、メイン ノードの下にandノード<item>
の長いリストが表示されますが、どのandノードが一緒に属しているかを知る手段がありません。 ..<itemid>
<subitems>
<items>
<itemid>
<subitems>
XML を次のように変更する必要があります。
<job>
<jobid>4711</jobid>
<items>
<item>
<itemid>1</itemid>
<subitems>
<subitemid>1</subitemid>
<subitemid>2</subitemid>
</subitems>
</item>
<item>
<itemid>2</itemid>
<subitems>
......
</subitems>
</item>
... (possibly more <item> nodes) ....
</items>
</job>
次に、基本的に前の質問で使用したのと同じコードを使用できます-3つのレベルをカバーするように拡張されました:
CREATE PROCEDURE dbo.SaveJobs (@input XML)
AS BEGIN
;WITH JobsData AS
(
SELECT
JobID = JobNode.value('(jobid)[1]', 'int'),
ItemID = ItemNode.value('(itemid)[1]', 'int'),
SubItemID = SubItemNode.value('.', 'int')
FROM
@input.nodes('/jobs/job') AS TblJobs(JobNode)
CROSS APPLY
JobNode.nodes('items/item') AS TblItems(ItemNode)
CROSS APPLY
ItemNode.nodes('subitems/subitem') AS TblSubItems(SubItemNode)
)
INSERT INTO dbo.tblDummy(JobID, ItemID, SubItemID)
SELECT JobID, ItemID, SubItemID
FROM JobsData
END
基本的に、XML ノードの 3 つの「リスト」が必要です。
- まず、値
<jobs>/<job>
を取得するためにすべてのノードのリストが必要ですjobid
- これらのジョブ ノードごとに、値
<items>/<item>
を取得するためにネストされたリストも取得する必要があります。itemid
- 各ノードから、次のリストも取得します
<subitems>/<subitem>
これでうまくいく可能性が高いですが、かなり遅くなる可能性があります (.nodes()
関数への 3 つのネストされた呼び出し!)。
アップデート:
OK、最初の呼び出しは基本的に単一の列を持つ@input.nodes('/jobs/job') AS TblJobs(JobNode)
「疑似」テーブルを作成し、XML の各要素はその疑似テーブルの行に格納されているため、最初の行の列には次の XML が含まれます。TblJobs
JobNode
<job>
JobNode
<job>
<jobid>4711</jobid>
<items>
<item>
<itemid>1</itemid>
<subitems>
<subitemid>1</subitemid>
<subitemid>2</subitemid>
</subitems>
</item>
<item>
<itemid>2</itemid>
<subitems>
......
</subitems>
</item>
... (possibly more <item> nodes) ....
</items>
</job>
さらに各行には、<job>
内部の後続の各要素の追加の XML フラグメントが含まれます。<jobs>
これらの XML フラグメントのそれぞれから、2 番目の呼び出し
CROSS APPLY JobNode.nodes('items/item') AS TblItems(ItemNode)
再び XML フラグメントのリストを選択して、現在扱っているノード内の各ノードの XML フラグメントを含むTblItems
単一の列を持つ疑似テーブル ( ) にします。ItemNode
<item>
<job>
したがって、この疑似テーブルの最初の行には次のものが含まれます。
<item>
<itemid>1</itemid>
<subitems>
<subitemid>1</subitemid>
<subitemid>2</subitemid>
</subitems>
</item>
2行目には
<item>
<itemid>2</itemid>
<subitems>
......
</subitems>
</item>
等々。
そして、3 番目の呼び出し (ご想像のとおり) は、XML 要素のリストを行として抽出し、疑似テーブルに入れ<subitem>
ます (XML フラグメントのノードごとに 1 つのエントリ)。
更新#2:
「JobID = JobNode.value('(jobid)[1]', 'int')」コード行は初めてです
OK -<Job>
あなたが持っている XML フラグメントを考えると:
<job>
<jobid>4711</jobid>
<items>
......
</items>
</job>
この呼び出しは、その XML に対して.value()
この XPath 式 ( ) を実行するだけで、基本的にスニペットを取得します。次に、そのノードの値(内部テキスト) を抽出し、呼び出しの 2 番目のパラメーターは、これを解釈する SQL データ型を定義します。つまり、基本的にノードから を取得し、それをjobid
<jobid>4711</jobid>
.value()
4711
<jobid>
int