Question

Je suis en train de générer des XML avec différents niveaux d'imbrication, et au risque de trop simplifier, le XML de sortie sera lâchement du format:

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

Le schéma de base de données que j'ai hérité de ce qui arrive à avoir des charges stockées dans des tables différentes, ce qui signifie que les suppléments sont stockés différemment selon la table où la charge était.

Étant donné que vous ne pouvez pas utiliser UNIONs avec FOR XML, je l'ai fait quelques UNIONing dans un CTE, donc quelque chose le long de la lignes de:

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

, qui est très à proximité, ce qui donne (Notez le <surcharge> imbriquée):

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

Mais je dois trouver un moyen d'obtenir la requête de fin d'inclure la valeur d'une colonne XML à traiter comme le contenu de l'élément, plutôt que comme un nouvel élément. Est-ce possible, ou dois-je prendre une nouvelle approche?

Était-ce utile?

La solution 2

Il semble que nommer le (faux) colonne comme « * » utilisera que le contenu de cette colonne que le contenu de l'élément, en changeant ainsi le SQL comme ci-dessous fait fonctionner:

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

Autres conseils

Vous avez une requête de colonne qui renvoie des lignes mulitple j'attendre la requête que vous postez pour donner l'erreur (@charge, @rate, et un type XML.):

  

Une seule expression peut être spécifiée   dans la liste de sélection lorsque la sous-requête   n'est pas introduite par exists.

Cependant, qui est facilement corrigé en déplaçant la requête à un outer apply. Pour supprimer la double élément surcharge, vous pouvez déplacer les noms de colonnes XML jusqu'à au fond que possible, comme:

;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

imprimerait, par exemple:

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

Le premier élément provient de la partie supérieure de l'Union, où surcharge = null.

Je pense que vous pouvez le faire en supprimant le type de nœud racine dans votre déclaration « pour le chemin xml ( 'en supplément) ». Autrement dit, l'utilisation "pour le chemin xml ( '')" à la place.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top