XML query () работает, value () требует одноэлементного найденного xdt: untypedAtomic - PullRequest
32 голосов
/ 19 августа 2009

У меня есть типизированный XML-документ, хранящийся в виде текста. Поэтому я использую CONVERT типа данных в xml с помощью выражения Common Table, чтобы можно было использовать методы XML:

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

Запрос работает, возвращая мне элемент. Но меня интересует только значение:

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

Это дает мне следующую ошибку:

'value ()' требует одиночного (или пустой последовательности) найденного операнда типа 'xdt: untypedAtomic *'

То, что я гуглил, говорит о том, что XPATH / XQUERY должен быть в круглых скобках и / или нуждается в "[1]" - ни один из них не сработал. В xml есть только один элемент студенческого идентификатора, хотя я предполагаю, что схема допускает больше?

Кроме того, существует множество значений элементов, которые я хотел бы получить - есть ли способ объявить пространство имен один раз, а не на вызов метода?

Ответы [ 3 ]

66 голосов
/ 19 августа 2009

Вам нужно использовать это:

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

Вам нужно поместить свой XPath в ( ... ) и добавить [1], чтобы просто выбрать первое значение этой последовательности.

8 голосов
/ 22 августа 2011

Я верю, что это также может сделать

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 голосов
/ 13 мая 2015

Для тех, кто интересуется производительностью, я выполнил запрос, чтобы сравнить эти подходы, и первый вариант с "() и добавить [1]" был НАМНОГО быстрее, чем ".query ('strFranchise'). Value ('.', ...)».

Разница в плане выполнения составляла от 15% до 85% при выполнении одного за другим для одних и тех же данных. Так что () [1] более чем в 5 раз быстрее! План выполнения сильно отличается.

...