2013-06-29 6 views
4

Я выполняю запрос к колонку типа данных XML в SQL Server 2012. Пример данных:SQL Server XQuery возвращает ошибку

<ns:Resume xmlns:ns="http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/Resume"> 
    <ns:Name> 
    <ns:Name.Prefix></ns:Name.Prefix> 
    <ns:Name.First>Shai</ns:Name.First> 
    <ns:Name.Middle></ns:Name.Middle> 
    <ns:Name.Last>Bassli</ns:Name.Last> 
    <ns:Name.Suffix></ns:Name.Suffix> 
    </ns:Name> 
    ... 
</ns:Resume> 

Я пытаюсь написать запрос, чтобы вернуть первый имена.

Этот запрос возвращает список имен, как ожидалось:

WITH XMLNAMESPACES ('http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/Resume' AS ns) 
SELECT [Resume].query('(//ns:Name.First)').value('.[1]', 'nvarchar(100)') 
FROM HumanResources.JobCandidate; 

Однако этот запрос возвращает ошибку:

WITH XMLNAMESPACES ('http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/Resume' AS ns) 
SELECT [Resume].value('(//ns:Name.First)[1]', 'nvarchar(100)') 
FROM HumanResources.JobCandidate; 

Ошибка:

Msg 9314, Level 16, State 1, Line 2
XQuery [HumanResources.JobCandidate.Resume.value()]: Cannot implicitly atomize or apply 'fn:data()' to complex content elements, found type 'xs:anyType' within inferred type '(element(ns{ http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/Resume }:Name.First,xs:string) | element(ns{ http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/Resume }:Name.First,xs:anyType)) ?'.

Там какая-то базовое понимание что мне здесь не хватает, но я не уверен, что это такое. Может кто-нибудь просветить меня? Почему второй запрос возвращает ошибку?

ответ

1

Ваше выражение XPath может привести к возврату нескольких строк для каждой строки в таблице SQL Server. Вы должны будете использовать CROSS APPLY и вызов .nodes(), чтобы получить эту информацию, вы после:

WITH XMLNAMESPACES ('http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/Resume' AS ns) 
SELECT 
    JobCandidateID, 
    ResNames.value('(ns:Name.First)[1]', 'nvarchar(100)') 
FROM 
    HumanResources.JobCandidate 
CROSS APPLY 
    [Resume].nodes('/ns:Resume/ns:Name') AS XTbl(ResNames) 

Это должно вернуть все JobCandidateID ценности и все имена, определенные в столбце Resume XML для каждой строки в Таблица.

Если вы можете быть уверены, что есть только когда-либо будет один <name> тег в столбце XML, то вы могли бы также сократить это:

WITH XMLNAMESPACES ('http://schemas.microsoft.com/sqlserver/2004/07/adventure-works/Resume' AS ns) 
SELECT 
    JobCandidateID, 
    [Resume].value('(/ns:Resume/ns:Name/ns:Name.First)[1]', 'nvarchar(100)') 
FROM 
    HumanResources.JobCandidate 
+0

Я уверен, что вы правильные marc_s, но вещи как это в XML, всегда бросайте меня за цикл. Можете ли вы объяснить, почему '' .. [1] ''уже присутствует, не решает проблему, возможно, возвращая более одного элемента в строку? thnx .. – RBarryYoung

+0

@RBarryYoung: да, я думал, что '[1]' тоже сделает трюк! Но появляется (из сообщения об ошибке), что при поиске '// ns: Name.First' каким-то образом обработка XQuery в SQL Server предполагает, что есть' Name.First, xs: string' и вторая 'Name.First, xs: any' в коллекции XML-схем (опять же: я не уверен, почему это происходит - я только видел, что это случается иногда). В этом случае процессор XQuery не может понять, что такое элемент 'Name.First' (какой тип) и таким образом barfs вверх –

+0

Итак, используя' '(/ns:Resume/ns:Name/ns:Name.First)[1 ] ''вместо'' (//ns:Name.First) [1] '' делает разницу? Зачем? – Seiker

Смежные вопросы