简体   繁体   English

XML 文档到 SQL Server 查询

[英]XML Document to SQL Server Query

How to get data from XML file to SQL query, following code is not working.如何从 XML 文件获取数据到 SQL 查询,以下代码不起作用。

<FVDL>
        <EngineData>
           <RuleInfo>
             <Rule id="13EFF385-69A9-494A-9C67-951FEDAB25ED">
               <MetaInfo>
                 <Group name="package">Python Core xml</Group>
                 <Group name="inputsource">XML Document</Group>
                 <Group name="audience">broad</Group>
               </MetaInfo>
             </Rule>
            <Rule id="E9DB1C0E-025E-4EBF-A804-6C3DA413E652">
               <MetaInfo>
                 <Group name="altcategoryMIS">Python Core zipfile</Group>
                 <Group name="altcategoryGDPR">Access Violation</Group>
               </MetaInfo>
             </Rule>  
           </RuleInfo>
        </EngineData>
    </FVDL>
             
    
    USE OPENXMLTesting
    GO
    
    DECLARE @XML AS XML, @hDoc AS INT
    
    SELECT @XML = XMLData FROM XMLwithOpenXML
    
    EXEC sp_xml_preparedocument @hDoc OUTPUT, @XML
    
    Select ID, name, [Group]
    FROM OPENXML(@hDoc, 'FVDL/EngineData/RuleInfo') 
    
    WITH  
    (
    ID [varchar](100) 'Rule/@id',
    [name] [varchar](100) 'Rule/MetaInfo/Group/@name',
    [Group] [varchar](1000) 'MetaInfo/Group/.. '
    )  
    
    EXEC sp_xml_removedocument @hDoc

Looking for result like this寻找这样的结果

ID ID Name姓名 Group团体
13EFF385-69A9-494A-9C67-951FEDAB25ED 13EFF385-69A9-494A-9C67-951FEDAB25ED package包裹 Python Core xml Python 核心 xml
13EFF385-69A9-494A-9C67-951FEDAB25ED 13EFF385-69A9-494A-9C67-951FEDAB25ED nputsource输入源 XML Document XML 文件
13EFF385-69A9-494A-9C67-951FEDAB25ED 13EFF385-69A9-494A-9C67-951FEDAB25ED audience观众 broad广阔
E9DB1C0E-025E-4EBF-A804-6C3DA413E652 E9DB1C0E-025E-4EBF-A804-6C3DA413E652 altcategoryMIS管理信息系统 Python Core zipfile Python 核心压缩文件
E9DB1C0E-025E-4EBF-A804-6C3DA413E652 E9DB1C0E-025E-4EBF-A804-6C3DA413E652 altcategoryGDPR其他类别GDPR Access Violation访问冲突

Please try the following solution.请尝试以下解决方案。

Starting from SQL Server 2005 onwards, it is better to use XQuery language, based on the w3c standards, while dealing with the XML data type.从 SQL Server 2005 开始,在处理 XML 数据类型时,最好使用基于 w3c 标准的 XQuery 语言。

Microsoft proprietary OPENXML and its companions sp_xml_preparedocument and sp_xml_removedocument are kept just for backward compatibility with the obsolete SQL Server 2000. Their use is diminished just to very few fringe cases.保留 Microsoft 专有的OPENXML及其伙伴sp_xml_preparedocumentsp_xml_removedocument只是为了与过时的 SQL Server 2000 向后兼容。它们的使用减少到很少的边缘情况。 It is strongly recommended to re-write your SQL and switch it to XQuery.强烈建议重新编写您的 SQL 并将其切换到 XQuery。

SQL SQL

-- DDL and sample data population, start
DECLARE @tbl TABLE (ID INT IDENTITY PRIMARY KEY, xmldata XML);
INSERT INTO @tbl (xmldata) VALUES
(N'<FVDL>
    <EngineData>
        <RuleInfo>
            <Rule id="13EFF385-69A9-494A-9C67-951FEDAB25ED">
                <MetaInfo>
                    <Group name="package">Python Core xml</Group>
                    <Group name="inputsource">XML Document</Group>
                    <Group name="audience">broad</Group>
                </MetaInfo>
            </Rule>
            <Rule id="E9DB1C0E-025E-4EBF-A804-6C3DA413E652">
                <MetaInfo>
                    <Group name="altcategoryMIS">Python Core zipfile</Group>
                    <Group name="altcategoryGDPR">Access Violation</Group>
                </MetaInfo>
            </Rule>
        </RuleInfo>
    </EngineData>
</FVDL>');
-- DDL and sample data population, end

SELECT p.value('@id', 'UNIQUEIDENTIFIER') AS ID
    , c.value('@name', 'VARCHAR(30)')AS [Name]
    , c.value('(./text())[1]', 'VARCHAR(30)')AS [Group]
FROM @tbl
    CROSS APPLY xmldata.nodes('/FVDL/EngineData/RuleInfo/Rule') AS t1(p)
    CROSS APPLY t1.p.nodes('MetaInfo/Group') AS t2(c);

Output输出

+--------------------------------+-----------------+---------------------+
|               ID               |      Name       |       Group         |
+--------------------------------+-----------------+---------------------+
| 13EFF385-69A9-494A-9C67-951FED | package         | Python Core xml     |
| 13EFF385-69A9-494A-9C67-951FED | inputsource     | XML Document        |
| 13EFF385-69A9-494A-9C67-951FED | audience        | broad               |
| E9DB1C0E-025E-4EBF-A804-6C3DA4 | altcategoryMIS  | Python Core zipfile |
| E9DB1C0E-025E-4EBF-A804-6C3DA4 | altcategoryGDPR | Access Violation    |
+--------------------------------+-----------------+---------------------+

OPENXML is a bit wonky and is outdated. OPENXML 有点不稳定并且已经过时了。 If you need to use it, you need to provide the path down to <Group> and then work your way back up to the other elements.如果您需要使用它,您需要提供到<Group>的路径,然后再回到其他元素。 This should do it for you based on your sample XML.这应该根据您的示例 XML 为您完成。

DECLARE @XML XML = N'<FVDL>
        <EngineData>
           <RuleInfo>
             <Rule id="13EFF385-69A9-494A-9C67-951FEDAB25ED">
               <MetaInfo>
                 <Group name="package">Python Core xml</Group>
                 <Group name="inputsource">XML Document</Group>
                 <Group name="audience">broad</Group>
               </MetaInfo>
             </Rule>
            <Rule id="E9DB1C0E-025E-4EBF-A804-6C3DA413E652">
               <MetaInfo>
                 <Group name="altcategoryMIS">Python Core zipfile</Group>
                 <Group name="altcategoryGDPR">Access Violation</Group>
               </MetaInfo>
             </Rule>  
           </RuleInfo>
        </EngineData>
    </FVDL>'
    
DECLARE @hDoc AS INT
    
EXEC sp_xml_preparedocument @hDoc OUTPUT, @XML
    
Select ID, name, [Group]
FROM OPENXML(@hDoc, 'FVDL/EngineData/RuleInfo/Rule/MetaInfo/Group') 
WITH  
(
    id [varchar](100) '../../@id',
    [name] [varchar](100) '@name',
    [Group] [varchar](1000) '.'
)  
    
EXEC sp_xml_removedocument @hDoc

I strongly suggest you don't use OPENXML , as it has many issues.我强烈建议您不要使用OPENXML ,因为它有很多问题。

Instead use the newer XQuery functions, which are far simpler to use而是使用较新的 XQuery 函数,它们使用起来要简单得多

  • Note how one .nodes feeds into the next.请注意一个.nodes如何馈入下一个。 This is only necessary because there are two separate levels of nodes that need breaking into separate rows.这只是必要的,因为有两个单独的节点级别需要分成单独的行。
SELECT
    ID = rl.value('@id','uniqueidentifier'),
    [name] = grp.value('@name', 'varchar(100)'),
    [Group] = grp.value('text()[1]','varchar(1000)')
FROM XMLwithOpenXML
CROSS APPLY XMLData.nodes('FVDL/EngineData/RuleInfo/Rule') x1(rl)
CROSS APPLY x1.rl.nodes('MetaInfo/Group') x2(Grp);

db<>fiddle 数据库<>小提琴

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM