Reputation: 743
Environment: SQL Server 2012.
Say I have a table Message with xml column WordIndex. I also have a table Word which has WordId and WordText. Xml for Message.WordIndex has the following schema:
<xs:schema attributeFormDefault="unqualified"
elementFormDefault="qualified"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://www.example.com">
<xs:element name="wi">
<xs:complexType>
<xs:sequence>
<xs:element maxOccurs="unbounded" name="w">
<xs:complexType>
<xs:sequence>
<xs:element maxOccurs="unbounded" name="p" type="xs:unsignedByte" />
</xs:sequence>
<xs:attribute name="wid" type="xs:unsignedByte" use="required" />
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
and some data to go with it:
<wi xmlns="http://www.example.com">
<w wid="1">
<p>28</p>
<p>72</p>
<p>125</p>
</w>
<w wid="4">
<p>89</p>
</w>
<w wid="5">
<p>11</p>
</w>
</wi>
I also have SQL queries with XQuery code like this:
with WordIds as
(
select distinct
t.c.value('@wid', 'int') as XmlWordId
from
Message as m
cross apply
m.WordIndex.nodes('/wi/w') as t(c)
inner join Word as w
on w.WordId = t.c.value('@wid', 'int')
-- some more joins go here ...
)
select
count(*)
from
WordIds
and this (this one doesn't work, since I started to introduce schema into it):
with xmlnamespaces('http://www.example.com' as ns)
select
wi.Position,
w.WordId,
w.WordText
from
(
select
t.c.value('.', 'int') as Position,
t.c.value('../@wid', 'int') as WordId
from
Message as m
cross apply m.WordIndex.nodes('//p') as t(c)
where
m.MessageId = @MessageId
) as wi
inner join Word as w
on w.WordId = wi.WordId
order by
wi.Position
Question:
What is the proper syntax to qualify arguments to calls to .value() and .nodes()? I get errors that I don't fully understand:
XQuery [Message.WordIndex.value()]: 'value()' requires a singleton (or empty sequence), found operand of type 'xdt:anyAtomicType *'
Upvotes: 0
Views: 541
Reputation: 14389
It's just one of the syntactic rules, quote from:
http://msdn.microsoft.com/en-us/library/ms175972.aspx
"When a CTE is used in a statement that is part of a batch, the statement before it must be followed by a semicolon."
Upvotes: 1
Reputation: 14389
Try these queries:
;with xmlnamespaces( default 'http://www.example.com'), WordIds as
(
select distinct
t.c.value('@wid', 'int') as XmlWordId
from
Message as m
cross apply
m.WordIndex.nodes('/wi/w') as t(c)
inner join Word as w
on w.WordId = t.c.value('@wid', 'int')
-- some more joins go here ...
)
select
count(*)
from
WordIds
;with xmlnamespaces( default 'http://www.example.com')
select
w.c.value('@wid', 'INT') wid,
p.c.value('.', 'INT') p
from message m
cross apply m.wordIndex.nodes('wi/w') w(c)
cross apply w.c.nodes('p') p(c)
Generally, try and avoid the parent axis(..) as it has performance issues. Instead use multiple CROSS APPLY to drill down into the xml left to right.
Have a look through this article for more info on namespaces:
Adding Namespaces Using WITH XMLNAMESPACES
http://msdn.microsoft.com/en-us/library/ms177400.aspx
Upvotes: 2