SQL 服务器检索所有值

SQL Server retrieve all values

我有一个 table,我们称它为 TBL,列类型为 XML

XML 列(此处称为 xml)的格式为:

<START xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="87jjhanM">
    <Header xmlns="">
    ...
    </Header>
    <Fetch xmlns="">
    .....
    </Fetch>
    <Send xmlns="">
        <Supplier>
            <Deals>
                <Deal>
                   <Field1> </Field1>
                   <Field2> </Field2>
                </Deal>
            </Deals>
        </Supplier>
        <Supplier>
            <Deals>
                <Deal>
                   <Field1> </Field1>
                   <Field2> </Field2>
                </Deal>
            </Deals>
        </Supplier>
    </Send>
</START>

请注意,每个 XML 文档可以有多个 <Supplier> 标签。我感兴趣的是获取 Field1Field2.

的值

从阅读 How can I query a SQL Server XML column and return all values for a specific node? and Getting multiple records from xml column with value() in SQL Server 看来我应该使用某种交叉应用。

我似乎无法让它发挥作用。使用 value(),我完全有能力找到第一个实例,但是使用 nodes(),我惨遭失败(SQL 服务器)。

我为获取所有 Field1 值而进行的公然剽窃尝试(此处仅针对 Field1)是:

SELECT  
    xml.value('(/Supplier/Deals/Deal/Field1[1])[1]', 'VARCHAR(100)') AS A
FROM    
    TBL
CROSS APPLY 
    xml.nodes('/Start/Send') x(A);

据我所知,它只是在每个 /Start/Send/ 下查找第一个值 /Supplier/Deals/Deal/Field1,但它不起作用 - 它只是 returns 0 行受影响(我我应该知道 XML 文件中存在的具体结构。

我相信这很容易,但我就是想不通为什么上面的方法不起作用。非常感谢任何帮助。

有很多错误可能与您的问题没有直接关系:XML 区分大小写(因此 START,而不是 Start),外部元素在命名空间 (87jjhanM) 等需要 WITH XMLNAMESPACES 之类的东西。但假设我们解决了所有问题:

WITH XMLNAMESPACES ('87jjhanM' AS n)
SELECT 
    A.value('Field1[1]', 'VARCHAR(100)') AS Field1, 
    A.value('Field2[1]', 'VARCHAR(100)') AS Field2
FROM    TBL
CROSS APPLY [xml].nodes('/n:START/Send/Supplier/Deals/Deal') x(A);

理想情况下,CROSS APPLY 应该在我们感兴趣的最低重复元素上完成(在本例中为 Deal),以使 value 查询尽可能简单,但是这不是硬性要求。

如果您想要 Field1Field2 中的所有值,但您不关心它们实际位于哪个字段,则可以按名称匹配:

WITH XMLNAMESPACES ('87jjhanM' AS n)
SELECT 
    A.value('.', 'VARCHAR(100)') AS [Field]
FROM    TBL
CROSS APPLY [xml].nodes('/n:START/Send/Supplier/Deals/Deal/*[local-name()="Field1" or local-name()="Field2"]') x(A);

如果你想,比如说,获取每个以 Field 开头的元素中的所有内容......那么事情会变得 很多 更烦人,但幸运的是你说你知道所涉及的 XML 的结构,所以这应该不是问题。

为了简洁起见,您试图缩短和清理它,这很好。但是 - 至少我是这么认为的 - 你做的有点过分了......

Jeroen Mostert 已经指向外壳 ("START"!="Start") 和命名空间。第一行有一个(相当奇怪的)默认名称空间,还有一些您根本不用的名称空间。

在你的 XML 中重复 xmlns="" 是非常危险的。这可能是由带有 FOR XML 和子选择的 T-SQL 命令创建的。关键是:这不是只是一些愚蠢的东西可以忽略,而是您正在为内部元素定义一个新的默认命名空间。这就是我使用命名空间通配符 *: 并省略命名空间声明的原因。

我在每个级别添加了一些额外的元素,并假设 <Deals> 下面可以有 1:n <Supplier>1:n <Deal> 个节点(在至少命名指向这一点)。您可以为此使用两个级别的 OUTER / CROSS APPLY

DECLARE @mockupTBL TABLE(ID INT IDENTITY, TheXml XML);
INSERT INTO @mockupTBL VALUES
(N'<START xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="87jjhanM">
   <Header xmlns="">
      <SomeNodeWithinHeader SomeValue="blah"/>
   </Header>
 <Fetch xmlns="">
      <SomeNodeWithinFetch SomeValue="blubb"/>
 </Fetch>
 <Send xmlns="">
   <Supplier>
     <SupplierRelatedData value="Sup1"/>
     <Deals>
       <Deal>
         <Field1>A1</Field1>
         <Field2>A2</Field2>
       </Deal>
       <Deal>
         <Field1>A3</Field1>
         <Field2>A4</Field2>
       </Deal>
     </Deals>
   </Supplier>
   <Supplier>
     <SupplierRelatedData value="Sup2"/>
     <Deals>
       <Deal>
         <Field1>B1</Field1>
         <Field2>B2</Field2>
       </Deal>
     </Deals>
   </Supplier>
 </Send>
 </START>');

 SELECT m.TheXml.value(N'(/*:START/Header/SomeNodeWithinHeader/@SomeValue)[1]',N'nvarchar(max)') ValueWithinHeader
       ,m.TheXml.value(N'(/*:START/Fetch/SomeNodeWithinFetch/@SomeValue)[1]',N'nvarchar(max)') ValueWithinFetch
       ,sup.value(N'(SupplierRelatedData/@value)[1]',N'nvarchar(max)') SupplierRelatedData
       ,deal.value(N'(Field1/text())[1]',N'nvarchar(max)') AS Field1
       ,deal.value(N'(Field2/text())[1]',N'nvarchar(max)') AS Field2
 FROM @mockupTBL AS m
 OUTER APPLY m.TheXml.nodes(N'/*:START/Send/Supplier') AS A(sup)
 OUTER APPLY A.sup.nodes(N'Deals/Deal') AS B(deal) 

结果

blah    blubb   Sup1    A1  A2
blah    blubb   Sup1    A3  A4
blah    blubb   Sup2    B1  B2