0

环境:SQL Server 2012。

假设我有一个带有 xml 列 WordIndex 的表 Message。我还有一个包含 WordId 和 WordText 的表格 Word。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 *'
4

2 回答 2

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 添加命名空间

http://msdn.microsoft.com/en-us/library/ms177400.aspx

于 2012-09-09T19:56:43.910 回答
1

这只是语法规则之一,引用自:

http://msdn.microsoft.com/en-us/library/ms175972.aspx

“当 CTE 用于作为批处理的一部分的语句中时,它之前的语句必须跟一个分号。”

于 2012-09-09T20:41:23.430 回答