Frage

Ich versuche, einige XML mit verschiedenen Ebenen der Verschachtelung zu erzeugen und auf die Gefahr von Über vereinfachen, wird die XML-Ausgabe lose von dem Format:

<invoice number="1">
 <charge code="foo" rate="123.00">
  <surcharge amount="10%" />
 </charge>
 <charge code="bar" />
</invoice>

Das Datenbankschema Ich habe für diesen geerbt geschieht Gebühren in unterschiedlichen Tabellen gespeichert haben, was bedeutet, dass Zuschläge unterschiedlich auf dem Tisch abgelegt basiert, von wo aus der Ladung war aus.

Da Sie nicht UNIONs mit FOR XML verwenden können, habe ich einige UNIONing in einem WAK getan, so etwas in der Zeilen:

WITH Charges ( [@code], [@rate], surcharge, InvoiceId ) AS (
    SELECT code AS [@Code], amount AS [@rate], NULL as surcharge, InvoiceId
    FROM item.charges
UNION ALL
    SELECT 
        code AS [@Code], 
        amount AS [@rate],
        (
             SELECT amount AS [@amount]
             FROM order.surcharges os
             WHERE oc.ChargeId = os.ChargeId
             FOR XML PATH('surcharge'), TYPE
        ), 
        InvoiceId
    FROM order.charges oc
)
SELECT
    Number AS [@number],
    (
         SELECT
             [@code],
             [@rate],
             surcharge
         FROM Charges
         WHERE Charges.InvoiceId = i.InvoiceId
    )
FROM Invoices i
FOR XML PATH( 'invoice' ), TYPE

Nun, das ist unglaublich in der Nähe, so dass (Beachten Sie die verschachtelte <surcharge>):

<invoice number="1">
 <charge code="foo" rate="123.00">
  <surcharge>
   <surcharge amount="10%" />
  </surcharge>
 </charge>
 <charge code="bar" />
</invoice>

Aber ich brauche einen Weg, um die End-Abfrage finden der Wert einer XML-Spalte zu schließen, wenn der Gehalt des Elements behandelt zu werden, und nicht als ein neues Element. Ist dies möglich, oder muss ich einen neuen Ansatz nehmen?

War es hilfreich?

Lösung 2

Es scheint, dass die (falsche) Spalte Benennung als „*“, dass der Inhalt dieser Spalte als Inhalt des Elements zu verwenden, so die SQL ändern, wie unten macht es Arbeit:

WITH Charges ( [@code], [@rate], surcharge, InvoiceId ) AS (
    SELECT code AS [@Code], amount AS [@rate], NULL as surcharge, InvoiceId
    FROM item.charges
UNION ALL
    SELECT 
        code AS [@Code], 
        amount AS [@rate],
        (
             SELECT amount AS [@amount]
             FROM order.surcharges os
             WHERE oc.ChargeId = os.ChargeId
             FOR XML PATH('surcharge'), TYPE
        ), 
        InvoiceId
    FROM order.charges oc
)
SELECT
    Number AS [@number],
    (
         SELECT
             [@code],
             [@rate],
             surcharge AS [*] -- Thsi will embed the contents of the previously generated XML in here.
         FROM Charges
         WHERE Charges.InvoiceId = i.InvoiceId
    )
FROM Invoices i
FOR XML PATH( 'invoice' ), TYPE

Andere Tipps

Sie haben eine Spalte Abfrage, die mulitple Zeilen zurückgibt ich die Abfrage Sie Beiträge verfassen erwarten würde, den Fehler zu geben (@charge, @rate und einen XML-Typen.):

Nur ein Ausdruck kann angegeben werden in der Auswahlliste, wenn die Unterabfrage nicht mit EXISTS eingeführt.

Allerdings, das ist festgelegt leicht durch die Abfrage zu einem outer apply bewegen. Um die Doppel surcharge Element zu entfernen, können Sie die XML-Spaltennamen so weit nach unten wie möglich, wie bewegen:

;WITH Charges (code, rate, surcharge, InvoiceId) AS 
    (
    SELECT  code, amount, NULL, InvoiceId
    FROM    @charges
    UNION ALL
    SELECT  code
    ,       amount
    ,       (
            SELECT  amount AS [@amount]
            FROM    @surcharges os
            WHERE   oc.ChargeId = os.ChargeId
            FOR XML PATH('surcharge'), TYPE
            )
    ,       InvoiceId
    FROM    @charges oc
)
SELECT  Number AS [@number]
,       c.code as [charge/@code]
,       c.rate as [charge/@rate]
,       c.surcharge as [charge]
FROM    @Invoices i
outer apply
        (
        SELECT  code
        ,       rate
        ,       surcharge
        FROM    Charges
        WHERE   Charges.InvoiceId = i.InvoiceId
        ) c
WHERE   i.InvoiceID = 1
FOR XML PATH( 'invoice' ), TYPE

Dies würde drucken, zum Beispiel:

<invoice number="1">
  <charge code="1" rate="1" />
</invoice>
<invoice number="1">
  <charge code="1" rate="1">
    <surcharge amount="1" />
  </charge>
</invoice>

Das erste Element kommt aus dem oberen Teil der Union, wo surcharge = null.

Ich glaube, Sie können dies tun, indem Sie den Wurzelknotentyp in Ihrer „für XML-Pfad (‚Aufschlag‘)“ Erklärung weggelassen wird. Das heißt, die Verwendung "für XML-Pfad ( '')" statt.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top