2009-08-19 3 views
31

Ich habe ein typisiertes XML-Dokument als Text gespeichert. So verwende ich den Datentyp xml Bekehrten durch eine Common Table Expression, um mit der Lage sein, XML Methoden zu verwenden:XML Query() funktioniert, Wert() erfordert Singleton gefunden xdt: untypedAtomic

WITH xoutput AS (
    SELECT CONVERT(xml, t.requestpayload) 'requestpayload' 
    FROM TABLE t 
    WHERE t.methodid = 1) 
SELECT x.requestpayload.query('declare namespace s="http://blah.ca/api";/s:validate-student-request/s:student-id') as studentid 
    FROM xoutput x 

Abfrage funktioniert, mir Rückkehr das Element. Aber ich bin nur daran interessiert, den Wert:

WITH xoutput AS (
    SELECT CONVERT(xml, t.requestpayload) 'requestpayload' 
    FROM TABLE t 
    WHERE t.methodid = 1) 
SELECT x.requestpayload.value('declare namespace s="http://blah.ca/api";/s:validate-student-request/s:student-id', 'int') as studentid 
    FROM xoutput x 

Das gibt mir die folgende Fehlermeldung:

'value()' requires a singleton (or empty sequence), found operand of type 'xdt:untypedAtomic *'

Was ich habe, sagt gegoogelt, dass die XPath/XQuery in Klammern sein muss und/oder braucht "[1]" - keiner hat funktioniert. Es gibt nur ein Student-ID-Element in der XML, obwohl ich denke, das Schema ermöglicht mehr?

Außerdem gibt es zahlreiche Elementwerte, die ich abrufen möchte - gibt es eine Möglichkeit, den Namespace einmal anstatt pro Methodenaufruf zu deklarieren?

Antwort

62

Sie müssen diese verwenden:

SELECT 
     x.requestpayload.value('declare namespace s="http://blah.ca/api"; 
      (/s:validate-student-request/s:student-id)[1]', 'int') 
    AS 
     studentid 
    FROM 
     xoutput x

Sie benötigen eine XPath in (...) setzen und ein [1] einfach wählen Sie den ersten Wert dieser Sequenz hinzuzufügen.

7

Ich glaube, das könnte auch tun:

SELECT 
    x.requestpayload.query('declare namespace s="http://blah.ca/api"; 
          /s:validate-student-request/s:student-id').value('.', 'int') 
    as studentid 
FROM xoutput x 
3

Für Leistung Interessiert ich eine Abfrage lief diese Ansätze und die erste Option mit „() und fügen Sie ein [1]“ vergleichen war viel schneller als ".query ('strFranchise'). value ('.', ...)".

Der Unterschied im Ausführungsplan war 15% bis 85%, wenn nacheinander mit denselben Daten gearbeitet wurde. So() [1] ist über 5 mal schneller! Der Ausführungsplan ist sehr unterschiedlich.

+0

Wie ich es verstehe, gibt '[1]' nur das erste Ergebnis zurück, während '.value ('.'' Alle Ergebnisse liefert. –