Extraire une valeur du champ XML SQL

En utilisant MS SQL Server, j'ai des données dans un champ XML (appelé XML ), qui est structuré comme ceci:

<Transaction01> <TransactionSetPurpose>Insert</TransactionSetPurpose> <POHeader> <PO_NBR>LG40016181</PO_NBR> </POHeader> </Transaction01> 

J'essaie de créer une requête SQL pour récupérer une autre colonne appelée SubmittedDate, avec le PO_NBR de ce champ XML. Étant nouveau pour XPath, j'ai lu de nombreux exemples et essayé à la fois la requête et la valeur , mais je n'ai pas encore réussi. Par exemple:

 SELECT SubmittedDate, XML.query('data(/POHeader/PO_NBR)') as PO_NBR FROM SubmitXML 

Cela me donne juste une colonne vide. Après avoir obtenu un test de travail de Quassnoi, j'ai travaillé de son XML vers le mien, et j'ai découvert que le problème était les attributes xmlns et xmlns: i dans le nœud racine:

 <Transaction01 xmlns="http://services.iesltd.com/" xmlns:i="http://www.w3.org/2001/XMLSchema-instance"> 

Alors, comment puis-je contourner cela?

 SELECT SubmittedDate, XML.query('data(/Transaction01/POHeader/PO_NBR)') as PO_NBR FROM SubmitXML 

Vous XPath origine, /POHeader/PO_NBR , supposé que POHeader est le nœud racine (qui ne l'est pas).

Un exemple de requête à vérifier:

 DECLARE @myxml XML SET @myxml = ' <Transaction01> <TransactionSetPurpose>Insert</TransactionSetPurpose> <POHeader> <PO_NBR>LG40016181</PO_NBR> </POHeader> </Transaction01>' SELECT @myxml.query('data(/Transaction01/POHeader/PO_NBR)') 

Si Transaction01 n'est pas toujours le noeud racine (ce qui n'est pas une bonne chose), utilisez ceci:

 SELECT SubmittedDate, XML.query('data(/*/POHeader/PO_NBR)') as PO_NBR FROM SubmitXML 

Généralement, le schéma XML suppose que les noms des points sont corrigés et que les parties variables vont aux données des nœuds et des attributes plutôt que dans leurs noms, comme ceci:

 <Transaction id='01'> <TransactionSetPurpose>Insert</TransactionSetPurpose> <POHeader> <PO_NBR>LG40016181</PO_NBR> </POHeader> </Transaction> 

Mettre à jour:

Vous devez déclarer les namespaces à l'aide de WITH XMLNAMESPACES :

 DECLARE @myxml XML SET @myxml = ' <Transaction01 xmlns="http://services.iesltd.com/" xmlns:i="http://www.w3.org/2001/XMLSchema-instance"> <TransactionSetPurpose>Insert</TransactionSetPurpose> <POHeader> <PO_NBR>LG40016181</PO_NBR> </POHeader> </Transaction01>' ; WITH XMLNAMESPACES ( 'http://services.iesltd.com/' AS m ) SELECT @myxml.query ( 'data(/*/m:POHeader/m:PO_NBR)' ) 

Mise à jour 2:

Trier:

 ; WITH XMLNAMESPACES ( 'http://services.iesltd.com/' AS m ) SELECT SubmittedDate, XML.value('(/*/m:POHeader/m:PO_NBR)[1]', 'NVARCHAR(200)') AS po_nbr FROM SubmitXML ORDER BY po_nbr 

Si vous voulez éviter le encoding en dur de Transaction01, vous pouvez essayer ceci:

 SELECT SubmittedDate, XML.query('data(//POHeader/PO_NBR)') as PO_NBR FROM SubmitXML 

PAR EXEMPLE:

 CREATE TABLE #TEMP (XMLTEXT XML) INSERT INTO #TEMP SELECT '<Transaction01> <TransactionSetPurpose>Insert</TransactionSetPurpose> <POHeader> <PO_NBR>LG40016181</PO_NBR> </POHeader> </Transaction01> ' SELECT XMLTEXT.query('data(//POHeader/PO_NBR)') as PO_NBR FROM #TEMP