2017-10-26 7 views
0

FOR XML EXPLICITを使用してXMLにフォーマットする必要がある、かなり大きなクエリ(1ダースのテーブルに25個のタグ、〜1500行)があります。残念なことに、このファイルのコンシューマはCDATAタグの使用を要求しています。そうしないと、FOR XML PATHが使用されます。FOR XML EXPLICITのORDER BY句

これは私が探しているものです:

<elem elem_att1="..." elem_att2="1" elem_att3="..."> 
    <a>...</a>    
    <b>...</b> 
    <c>...</c> 
    <d>...</d> 
    <e> 
     <e1 e1_att1="..." e1_att2="1"> 
      <e11>...</e11> 
      <e12><![CDATA[...]]></e12> 
      <e13><![CDATA[...]]></e13> 
     </e1> 
     <e1 e1_att1="..." e1_att2="2"> 
      <e11>...</e11> 
      <e12><![CDATA[...]]></e12> 
      <e13><![CDATA[...]]></e13> 
     </e1> 
     <e1 e1_att1="..." e1_att2="3"> 
      <e11>...</e11> 
      <e12><![CDATA[...]]></e12> 
      <e13><![CDATA[...]]></e13> 
     </e1> 
    </e> 
    <f> 
     <f1 f1_att1="..." f1_att2="..." /> 
     <f2 f2_att1="..." f2_att2="..." /> 
     <f3 f3_att1="..." f3_att2="..." /> 
    </f> 
</elem> 

は、次のタグと親のマッピングが正しくクエリでで定義されていると想定します

 Tag | Parent 
elem 2 | 1 
a  3 | 2 
b  4 | 2 
c  5 | 2 
d  6 | 2 
e  7 | 2 
e1 8 | 7 
e11 9 | 8 
e12 10 | 8 
e13 11 | 8 
f  12 | 2 
f1 13 | 12 
f2 14 | 12 
f3 15 | 12 

私は約90を得ていますそこにはクエリの%が、ユニバーサルテーブル内のタグの順序に関連する問題に遭遇しています。私は、テーブルの最初の2列に対して次のような出力を見ることが期待されるクエリから返さ:

Tag | Parent 
2 | 1 
3 | 2 
4 | 2 
5 | 2 
6 | 2 
7 | 2 <-- beginning of the "e" element 
12 | 2 <-- beginning of the "f" element 
13 | 12 
14 | 12 
15 | 12 
8 | 7 <--first instance of the "e1" element 
9 | 8 
10 | 8 
11 | 8 
8 | 7 <-- second instance of the "e1" element 
9 | 8 
10 | 8 
11 | 8 
8 | 7 <-- third and final instance of the "e1" element 
9 | 8 
10 | 8 
11 | 8 

Tag | Parent 
2 | 1 
3 | 2 
4 | 2 
5 | 2 
6 | 2 
7 | 2 <-- beginning of the "e" element 
8 | 7 <-- first instance of the "e1" element 
9 | 8 
10 | 8 
11 | 8 
8 | 7 <-- second instance of the "e1" element 
9 | 8 
10 | 8 
11 | 8 
8 | 7 <-- third and final instance of the "e1" element 
9 | 8 
10 | 8 
11 | 8 
12 | 2 <-- beginning of the "f" element 
13 | 12 
14 | 12 
15 | 12 

は代わりに、私は、クエリ出力の最初の2列としてこれを取得していますクエリはチョークと、次のエラーがスローされます

<elem elem_att1="..." elem_att2="1" elem_att3="..."> 
    <a>...</a>    
    <b>...</b> 
    <c>...</c> 
    <d>...</d> 
    <e /> 
    <f> 
     <f1 f1_att1="..." f1_att2="..." /> 
     <f2 f2_att1="..." f2_att2="..." /> 
     <f3 f3_att1="..." f3_att2="..." /> 
    </f> 
     <e1 e1_att1="..." e1_att2="1"> 
      <e11>...</e11> 
      <e12><![CDATA[...]]></e12> 
      <e13><![CDATA[...]]></e13> 
     </e1> 
     <e1 e1_att1="..." e1_att2="2"> 
      <e11>...</e11> 
      <e12><![CDATA[...]]></e12> 
      <e13><![CDATA[...]]></e13> 
     </e1> 
     <e1 e1_att1="..." e1_att2="3"> 
      <e11>...</e11> 
      <e12><![CDATA[...]]></e12> 
      <e13><![CDATA[...]]></e13> 
     </e1> 
    </e> 
</elem> 

明らかにこの線に沿って不正な形式のXMLを生成する

ここ

Msg 6833, Level 16, State 1, Line 2 
Parent tag ID 7 is not among the open tags. FOR XML EXPLICIT requires parent tags to be opened first. Check the ordering of the result set. 

order by句です:

order by [elem!2!att2], [e1!8!att2] 

私は

order by [elem!2!att2], tag, [e1!8!att2] 

order by句を変更した場合、クエリが正常に実行されますが、e1要素のすべての子レコードが最後の下にネストされていますe1要素:

<elem elem_att1="..." elem_att2="1" elem_att3="..."> 
    <a>...</a>    
    <b>...</b> 
    <c>...</c> 
    <d>...</d> 
    <e> 
     <e1 e1_att1="..." e1_att2="1" /> 
     <e1 e1_att1="..." e1_att2="2" /> 
     <e1 e1_att1="..." e1_att2="3"> 
      <e11>...</e11> 
      <e11>...</e11> 
      <e11>...</e11> 
      <e12><![CDATA[...]]></e12> 
      <e12><![CDATA[...]]></e12> 
      <e12><![CDATA[...]]></e12> 
      <e13><![CDATA[...]]></e13> 
      <e13><![CDATA[...]]></e13> 
      <e13><![CDATA[...]]></e13> 
     </e1> 
    </e> 
    <f> 
     <f1 f1_att1="..." f1_att2="..." /> 
     <f2 f2_att1="..." f2_att2="..." /> 
     <f3 f3_att1="..." f3_att2="..." /> 
    </f> 
</elem> 

実際の質問:

eの子供の人口よりも前に、結果セットに移入するfとその子供たちを引き起こしていますか?

これは比較的一般的な間違いであり、1500行以上のコードをコピーすることなく中継できるほどの抽象的な解決策であると考えています。

+1

を試してみましたので、長い時間問題を再現するために最小限のデータセットでスタンドアロンのシナリオを設定しようとする場合があります。この問題を回避するには、次の2つの可能性があります。1)消費者にXMLを読むには適切なツールを使用する必要があると伝えます。 'CDATA'は時代遅れですが、これはあなたの問題ではありません。 2)一意のプレースホルダを持つ 'PATH'を使ってXMLを作成し、文字列レベルで' REPLACE'を使って 'CDATA'を導入してください(今私は手を洗ってください)。ヒント:ネイティブXMLに 'CDATA'を含むstring-xmlを格納することはできません。自動的に置き換えられます。 – Shnugo

+0

ヒント@ Shnugoありがとう。私はそれがCDATAタグを取り戻す別のゴールラウンドの価値があるかもしれないと思います。 –

+0

消費者との議論のためのいくつかの議論:https://stackoverflow.com/a/39034049/5089204(およびそのリンク) 'CDATA'が暗黙的に失われるいくつかの状況があります(文字列とバックへの変換)。これらの「CDATA」をあなたのXMLに取り込むことができても、あなたはそれらを保持することは確実ではありません。 – Shnugo

答えて

0

私はこれを使用しましたが、あなたは申し訳ありませんが、私はEXPLICIT` `を経験していないよ...あなたはまだ助けが必要な場合は、

order by [elem!2!att2], [e], [e1!8!att2] 

または

order by [elem!2!att2], 7, [e1!8!att2] 
+0

これらの最初のエラーは、[e]は有効な列ではなく、2番目の列は発注の問題を修正できないというエラーが発生します。 –

+1

私はそれは長い時間だと言った!ごめんなさい! :-) – spodger