从 sql 数据库中的 xml 列返回所有非标准节点(重复)的列表

Posted

技术标签:

【中文标题】从 sql 数据库中的 xml 列返回所有非标准节点(重复)的列表【英文标题】:Return list of all non standard nodes (duplicate) from xml column in sql database 【发布时间】:2022-01-03 02:47:45 【问题描述】:

你能帮忙吗?

我有一个包含 NAME 和 XMLOUTPUT 列的表 'ED'

表格示例

Name              XMLOUTPUT
Person1           Snippet below

XMLOUTPUT 是

<Fields>
        <f Name="FIRSTNAME" ColumnOrder="0" SortSequence="-1">
            <FieldWasFlattened>false</FieldWasFlattened>
            <ParentView/>
        </f>
        <f Name="KEYNAME" ColumnOrder="1" SortSequence="-1">
            <FieldWasFlattened>false</FieldWasFlattened>
            <ParentView/>
        </f>
        <f Name="AGE" ColumnOrder="2" SortSequence="-1">
            <FieldWasFlattened>false</FieldWasFlattened>
            <ParentView/>
        </f>
        <f Name="BIRTHDATE" ColumnOrder="3" SortSequence="-1">
            <FieldWasFlattened>false</FieldWasFlattened>
            <ParentView/>
        </f>
        <f Name="LOOKUPID" ColumnOrder="4" SortSequence="-1">
            <FieldWasFlattened>false</FieldWasFlattened>
            <ParentView/>
        </f>
        <f Name="MIDDLENAME" ColumnOrder="5" SortSequence="-1">
            <FieldWasFlattened>false</FieldWasFlattened>
            <ParentView/>
        </f>
        <f Name="Blue (color)" ColumnOrder="6" SortSequence="-1">
            <FieldWasFlattened>false</FieldWasFlattened>
            <ParentView/>
        </f>
          <f Name="Red (color)" ColumnOrder="6" SortSequence="-1">
            <FieldWasFlattened>false</FieldWasFlattened>
            <ParentView/>
        </f>
          <f Name="Yellow (color)" ColumnOrder="6" SortSequence="-1">
            <FieldWasFlattened>false</FieldWasFlattened>
            <ParentView/>
        </f>
          <f Name="Green (color)" ColumnOrder="6" SortSequence="-1">
            <FieldWasFlattened>false</FieldWasFlattened>
            <ParentView/>
        </f>
    </Fields>

我要做的是选择 ED 表中的名称列以及 XMLOUTPUT 中具有(颜色)的任何名称

理想的输出是

NAME          XMLOUTPUT
Person1       Blue (color)
Person1       Red (color)
Person 1      Yellow (color)
Person1       Green (color)

到目前为止我最接近的是

select NAME as EDNAME,

    CAST(REPLACE(REPLACE(CONVERT(nvarchar(max),  XMLOUTPUT), '', ''), '', '')
    AS xml).value('(//*:f/@Name) [1] ', 'varchar(50)')
    as Color
    
    from ED
    
    where NAME = 'Person 1' 

但是由于语句中的 [1],这确实检索但仅检索第一个。 我正在寻找可以提取所有值的东西,@Name like '%color%'

感谢收看。

【问题讨论】:

【参考方案1】:

请尝试以下解决方案。

XPath XQuery contains() 函数非常适合您的场景。

SQL

-- DDL and sample data population, start
DECLARE @tbl TABLE (ID INT IDENTITY PRIMARY KEY, [Name] VARCHAR(20), XMLOUTPUT XML);
INSERT INTO @tbl ([Name], XMLOUTPUT) VALUES
('Person1', N'<Fields>
    <f Name="FIRSTNAME" ColumnOrder="0" SortSequence="-1">
        <FieldWasFlattened>false</FieldWasFlattened>
        <ParentView/>
    </f>
    <f Name="KEYNAME" ColumnOrder="1" SortSequence="-1">
        <FieldWasFlattened>false</FieldWasFlattened>
        <ParentView/>
    </f>
    <f Name="AGE" ColumnOrder="2" SortSequence="-1">
        <FieldWasFlattened>false</FieldWasFlattened>
        <ParentView/>
    </f>
    <f Name="BIRTHDATE" ColumnOrder="3" SortSequence="-1">
        <FieldWasFlattened>false</FieldWasFlattened>
        <ParentView/>
    </f>
    <f Name="LOOKUPID" ColumnOrder="4" SortSequence="-1">
        <FieldWasFlattened>false</FieldWasFlattened>
        <ParentView/>
    </f>
    <f Name="MIDDLENAME" ColumnOrder="5" SortSequence="-1">
        <FieldWasFlattened>false</FieldWasFlattened>
        <ParentView/>
    </f>
    <f Name="Blue (color)" ColumnOrder="6" SortSequence="-1">
        <FieldWasFlattened>false</FieldWasFlattened>
        <ParentView/>
    </f>
    <f Name="Red (color)" ColumnOrder="6" SortSequence="-1">
        <FieldWasFlattened>false</FieldWasFlattened>
        <ParentView/>
    </f>
    <f Name="Yellow (color)" ColumnOrder="6" SortSequence="-1">
        <FieldWasFlattened>false</FieldWasFlattened>
        <ParentView/>
    </f>
    <f Name="Green (color)" ColumnOrder="6" SortSequence="-1">
        <FieldWasFlattened>false</FieldWasFlattened>
        <ParentView/>
    </f>
</Fields>');
-- DDL and sample data population, end

SELECT ID, [Name]
    ,c.value('@Name', 'VARCHAR(30)') AS Result
FROM @tbl
    CROSS APPLY XMLOUTPUT.nodes('/Fields/f[contains(@Name, "(color)")]') AS t(c);

输出

+----+---------+----------------+
| ID |  Name   |     Result     |
+----+---------+----------------+
|  1 | Person1 | Blue (color)   |
|  1 | Person1 | Red (color)    |
|  1 | Person1 | Yellow (color) |
|  1 | Person1 | Green (color)  |
+----+---------+----------------+

【讨论】:

非常感谢 Yitzhak,我无法使用包含标准的解决方案,如果我省略它,它会输出所有行....-我懒惰地把它卡在一个带有交换的选择中为 CROSS APPLY XMLOUTPUT.nodes('//*:f') AS t(c)) 输出你的交叉应用行 @davie,很高兴听到建议的解决方案对您有用。请不要忘记将其标记为答案。

以上是关于从 sql 数据库中的 xml 列返回所有非标准节点(重复)的列表的主要内容,如果未能解决你的问题,请参考以下文章

MySQL从具有列名的select语句中的列列表中返回第一个非NULL值

在 SQL Server 中使用 value() 从 xml 列获取多条记录

在SQL Server中使用value()从xml列获取多个记录

sql 2005 聚合函数

订单列表查询SQL,查询出订单的数量和订单详细信息(包括订单中的所有商品)。

SQL 如何从单个列中的所有值创建 JSON 数组