【问题标题】:XML Document to SQL Server QueryXML 文档到 SQL Server 查询
【发布时间】:2021-12-02 08:09:11
【问题描述】:

如何从 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

寻找这样的结果

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

【问题讨论】:

    标签: sql sql-server xml openxml


    【解决方案1】:

    请尝试以下解决方案。

    从 SQL Server 2005 开始,最好使用基于 w3c 标准的 XQuery 语言,同时处理 XML 数据类型。

    保留 Microsoft 专有的 OPENXML 及其伙伴 sp_xml_preparedocumentsp_xml_removedocument 只是为了向后兼容过时的 SQL Server 2000。它们的使用减少到极少数的边缘情况。 强烈建议重写您的 SQL 并将其切换到 XQuery。

    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);
    

    输出

    +--------------------------------+-----------------+---------------------+
    |               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    |
    +--------------------------------+-----------------+---------------------+
    

    【讨论】:

      【解决方案2】:

      OPENXML 有点不稳定并且已经过时。如果您需要使用它,您需要提供到&lt;Group&gt; 的路径,然后按照自己的方式返回到其他元素。这应该根据您的示例 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
      

      【讨论】:

        【解决方案3】:

        我强烈建议你不要使用OPENXML,因为它有很多问题。

        改用较新的 XQuery 函数,这些函数使用起来要简单得多

        • 请注意.nodes 如何输入下一个。这只是必要的,因为有两个不同级别的节点需要分成不同的行。
        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

        【讨论】:

        • 只是想知道您的答案如何改进了 Yitzhak 的答案?
        • 你说得对,直到我注意到他才发帖,所以我就离开了
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-01-25
        • 1970-01-01
        • 2012-10-31
        • 2019-05-20
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多