环境:SQL Server 2012。
假设我有一个包含xml列WordIndex的表消息。我还有一个表Word,其中包含WordId和WordText。 Message.WordIndex的Xml具有以下模式:
<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>
和一些数据:
<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>
我还使用XQuery代码进行SQL查询,如下所示:
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
和这个(这个不起作用,因为我开始在其中引入模式):
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
问题:
限定参数以调用.value()和.nodes()的正确语法是什么? 我得到的错误是我不完全理解的:
XQuery [Message.WordIndex.value()]: 'value()' requires a singleton (or empty sequence), found operand of type 'xdt:anyAtomicType *'
答案 0 :(得分:2)
尝试以下查询:
;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)
通常,请尝试避免使用父轴(..),因为它存在性能问题。而是使用多个CROSS APPLY向下钻取到xml从左到右。
有关命名空间的更多信息,请查看本文:
使用WITH XMLNAMESPACES添加命名空间
答案 1 :(得分:1)
这只是一个句法规则,引自:
http://msdn.microsoft.com/en-us/library/ms175972.aspx
“当CTE在作为批处理一部分的语句中使用时,其前面的语句必须后跟分号。”