À l'aide de XQuery de SQL Server 2005, sélectionnez tous les nœuds avec une valeur d'attribut spécifique ou avec cet attribut manquant.

StackOverflow https://stackoverflow.com/questions/90023

  •  01-07-2019
  •  | 
  •  

Question

Mise à jour: exemple beaucoup plus complet.

Les deux premières solutions proposées vont dans le sens de ce que j'essayais de dire à de ne pas faire. Je ne peux pas connaître l'emplacement, il doit être capable de regarder tout l'arborescence du document. Donc, une solution dans ce sens, avec / Books / spécifiée car le contexte ne fonctionnera pas:

SELECT x.query('.') FROM @xml.nodes('/Books/*[not(@ID) or @ID = 5]') x1(x)

Question originale avec meilleur exemple:

À l'aide de l'implémentation XQuery de SQL Server 2005, je dois sélectionner tous les nœuds d'un document XML, une seule fois et en conservant leur structure d'origine, mais uniquement s'il leur manque un attribut particulier, ou si cet attribut a une valeur spécifique (transmise par paramètre). La requête doit également s’appliquer à l’ensemble du document XML (axe descendant ou autonome) au lieu de la sélectionner à une profondeur prédéfinie.

C’est-à-dire que chaque nœud apparaîtra dans le document résultant uniquement s’il possède l'attribut manquant à chacun de ses ancêtres, ou s'il possède l'attribut avec une seule valeur spécifique.

Par exemple:

S'il s'agissait du code XML:

    DECLARE @Xml XML
    SET @Xml =
    N'
<Library>
  <Novels>
    <Novel category="1">Novel1</Novel>
    <Novel category="2">Novel2</Novel>
    <Novel>Novel3</Novel>
    <Novel category="4">Novel4</Novel>
  </Novels>
  <Encyclopedias>
    <Encyclopedia>
      <Volume>A-F</Volume>
      <Volume category="2">G-L</Volume>
      <Volume category="3">M-S</Volume>
      <Volume category="4">T-Z</Volume>
    </Encyclopedia>
  </Encyclopedias>
  <Dictionaries category="1">
    <Dictionary>Webster</Dictionary>
    <Dictionary>Oxford</Dictionary>
  </Dictionaries>
</Library>
    '

Un paramètre de 1 pour catégorie entraînerait ceci:

<Library>
  <Novels>
    <Novel category="1">Novel1</Novel>
    <Novel>Novel3</Novel>
  </Novels>
  <Encyclopedias>
    <Encyclopedia>
      <Volume>A-F</Volume>
    </Encyclopedia>
  </Encyclopedias>
  <Dictionaries category="1">
    <Dictionary>Webster</Dictionary>
    <Dictionary>Oxford</Dictionary>
  </Dictionaries>
</Library>

Un paramètre de catégorie 2 pour la catégorie entraînerait ceci:

<Library>
  <Novels>
    <Novel category="2">Novel2</Novel>
    <Novel>Novel3</Novel>
  </Novels>
  <Encyclopedias>
    <Encyclopedia>
      <Volume>A-F</Volume>
      <Volume category="2">G-L</Volume>
    </Encyclopedia>
  </Encyclopedias>
</Library>

Je sais que XSLT convient parfaitement à ce travail, mais ce n’est pas une option. Nous devons accomplir cela entièrement dans SQL Server 2005. Toute implémentation n’utilisant pas XQuery convient également, dans la mesure où cela peut être fait entièrement en T-SQL.

Était-ce utile?

La solution

D'après votre exemple, vos objectifs ne sont pas clairs. Voulez-vous renvoyer un nouveau code XML avec tous les nœuds supprimés à l'exception de ceux qui remplissent la condition? Si c'est le cas, cela ressemble à un travail pour une transformation XSLT, qui, à mon avis, n'est pas intégré à MSSQL 2005 (peut être ajouté en tant que fichier UDF: http://www.topxml.com/rbnews/SQLXML/ re-23872_Performing-XSLT-Transforms-on-XML-Data-Stockées-dans-SQL-Server-2005.aspx ).

Si vous devez simplement renvoyer la liste des nœuds, vous pouvez utiliser cette expression:

//Book[not(@ID) or @ID = 5]

mais j'ai l'impression que ce n'est pas ce dont vous avez besoin. Nous vous aiderions si vous pouviez donner un exemple plus clair.

Modifier : cet exemple est en effet plus clair. Le meilleur que j'ai pu trouver est le suivant:

SET @Xml.modify('delete(//*[@category!=1])')
SELECT @Xml

L'idée est de supprimer du XML tous les nœuds dont vous n'avez pas besoin, afin de conserver la structure d'origine et les nœuds nécessaires. J'ai testé avec vos deux exemples et cela a donné le résultat souhaité.

Cependant, modifier a certaines restrictions - il semble que vous ne puissiez pas l'utiliser dans une instruction select, il doit modifier les données en place. Si vous devez renvoyer de telles données avec une sélection, vous pouvez utiliser une table temporaire dans laquelle copier les données d'origine, puis mettre à jour cette table. Quelque chose comme ça:

INSERT INTO #temp VALUES(@Xml)
UPDATE #temp SET data.modify('delete(//*[@category!=2])')

L’espoir que cela aide.

Autres conseils

La question n'est pas très claire, mais est-ce ce que vous cherchez?

DECLARE @Xml AS XML
        SET @Xml =
        N'
        <Books>
                <Book ID="1">Book1</Book>
                <Book ID="2">Book2</Book>
                <Book ID="3">Book3</Book>
                <Book>Book4</Book>
                <Book ID="5">Book5</Book>
                <Book ID="6">Book6</Book>
                <Book>Book7</Book>
                <Book ID="8">Book8</Book>
        </Books>
        '
DECLARE @BookID AS INT
SET @BookID = 5
DECLARE @Result AS XML

SET @result = (SELECT @xml.query('//Book[not(@ID) or @ID = sql:variable("@BookID")]'))
SELECT @result
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top