SQL使用OpenXML检索多个元素

时间:2017-06-29 12:49:17

标签: sql-server xml xpath xquery openxml

我查询使用OpenXML检索XML中主题元素之间的上限元素我不想要支持元素之间的上限。该查询非常适合检索一个值,但在有多个元素节点时会失败。

      <First>
         <Test id="83847">
            <subject>
               <cap>15</cap>
               <cap>25</cap>
               <cap>100</cap>
            </subject>
            <support>
               <cap>9</cap>
            </support>
          </Test>
        <Test id="83848">
            <subject>
               <cap>150</cap>
               <cap>2</cap>
               <cap>10</cap>
            </subject>
             <support>
               <cap>9</cap>
            </support>
          </Test>
      </First>

CREATE Table #XmlTemp(XmlField Xml);
Set Nocount On;
Insert Into #XmlTemp(XmlField)
Select '<First>
         <Test id="83847">
             <subject>
                <cap>15</cap>
                <cap>25</cap>
                <cap>100</cap>
             </subject>
             <support>
                <cap>9</cap>
             </support>
          </Test>
        <Test id="83848">
            <subject>
               <cap>150</cap>
               <cap>2</cap>
               <cap>10</cap>
            </subject>
             <support>
               <cap>9</cap>
            </support>
          </Test>
      </First>'As XmlField;

Declare @xmlData Xml;
Select @xmlData = XmlField From #XmlTemp;

Declare @document int;
Exec sp_xml_preparedocument @document Output, @xmlData, NULL;


SELECT ID,Cap FROM(
SELECT ID,Cap FROM OpenXml(@document,'./First/Test', 0) With (ID varchar(max)'./@id', Cap Varchar(max) './subject/cap')) alias

drop table #xmltemp

由于所涉及的测试,更改查询以使用.nodes方法是相当费时的,因此我希望尽可能保留OpenXML。 我只想检索ID,然后检索多个cap元素值。

感谢您的时间。

2 个答案:

答案 0 :(得分:1)

我看不出为什么使用.nodes的查询很复杂。刚

SELECT t.n.value('(/First/Test/@id)[1]', 'int') id
   , t.n.value('(.)[1]', 'int') cap
from @xmlData.nodes('./First/Test/subject/cap') t(n);

和OpenXML版本

SELECT ID,Cap FROM(
    SELECT ID,Cap 
    FROM OpenXml(@document,'./First/Test/subject/cap', 0) 
       With (ID varchar(max) '/First/Test/@id'
          , Cap Varchar(max) '.')) alias

已编辑问题的版本

SELECT ID,Cap FROM(
    SELECT ID,Cap 
    FROM OpenXml(@document,'/First/Test/subject/cap', 0) 
       With (ID varchar(max) '../../@id'
          , Cap Varchar(max) '.')) alias

它仅返回正确父级的subject/cap@id

    ID  Cap
1   83847   15
2   83847   25
3   83847   100
4   83848   150
5   83848   2
6   83848   10

答案 1 :(得分:0)

您的XML是双嵌套的。 1:n内的<Test>元素<First> 1:n以及<cap> <subject>元素CREATE Table #XmlTemp(XmlField Xml); Set Nocount On; Insert Into #XmlTemp(XmlField) Select '<First> <Test id="83847"> <subject> <cap>15</cap> <cap>25</cap> <cap>100</cap> </subject> <support> <cap>9</cap> </support> </Test> <Test id="83848"> <subject> <cap>150</cap> <cap>2</cap> <cap>10</cap> </subject> <support> <cap>9</cap> </support> </Test> </First>'As XmlField; 元素中的.nodes()元素。{/ p>

查询此问题的正确方法是严格转发到XML

<Test>

- 查询将使用.nodes()获取所有<cap>元素,然后再使用 SELECT t.value('@id', 'int') id ,c.value('text()[1]', 'int') cap from #XmlTemp AS tbl CROSS APPLY tbl.XmlField.nodes('/First/Test') AS A(t) CROSS APPLY A.t.nodes('subject/cap') AS B(c); GO DROP TABLE #XmlTemp; 获取相关的@Bean public DefaultMethodSecurityExpressionHandler defaultMethodSecurityExpressionHandler() { DefaultMethodSecurityExpressionHandler defaultMethodSecurityExpressionHandler = new DefaultMethodSecurityExpressionHandler(); defaultMethodSecurityExpressionHandler.setDefaultRolePrefix(""); return defaultMethodSecurityExpressionHandler; } @Bean public DefaultWebSecurityExpressionHandler defaultWebSecurityExpressionHandler() { DefaultWebSecurityExpressionHandler defaultWebSecurityExpressionHandler = new DefaultWebSecurityExpressionHandler(); defaultWebSecurityExpressionHandler.setDefaultRolePrefix(""); return defaultWebSecurityExpressionHandler; } 元素:

<bean id="defaultWebSecurityExpressionHandler" class="org.springframework.security.web.access.expression.DefaultWebSecurityExpressionHandler">
        <property name="defaultRolePrefix" value=""></property>
</bean>

<bean id="defaultMethodSecurityExpressionHandler" class="org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler">
        <property name="defaultRolePrefix" value=""></property>
</bean>