【问题标题】:SQL XQuery; Update attribute in typed XMLSQL XQuery;更新类型化 XML 中的属性
【发布时间】:2018-12-04 07:23:22
【问题描述】:

我正在尝试更新类型化 XML 中的属性。我过去通过在非类型化对象中构建 XML 然后将其设置为类型化对象来完成此操作(因此避免了这个问题),但我想知道如何直接修改类型化数据。

我的架构是:

if exists (select [xml_collection_id]
           from   sys.[xml_schema_collections] as [xsc]
           where  [xsc].name = 'xsc_test_stack'
                  and [xsc].[schema_id] = schema_id(N'chamomile'))
  drop xml schema collection [chamomile].[xsc_test_stack];

go

create xml schema collection [chamomile].[xsc_test_stack] as N'<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:chamomile="https://github.com/KELightsey/chamomile" targetNamespace="https://github.com/KELightsey/chamomile">
  <xsd:element name="test_stack">
    <xsd:complexType>
      <xsd:sequence>
        <xsd:element name="description" type="xsd:string" minOccurs="1" maxOccurs="1" />
        <xsd:element name="test_stack_detail" type="chamomile:any_complex_type" minOccurs="0" maxOccurs="unbounded" />
        <xsd:element name="test" type="chamomile:any_complex_type" minOccurs="0" maxOccurs="unbounded" />
      </xsd:sequence>
      <xsd:attribute name="name" type="xsd:string" use="required" />
      <xsd:attribute name="test_count" type="xsd:int" use="required" />
      <xsd:attribute name="pass_count" type="xsd:int" use="required" />
      <xsd:attribute name="timestamp" type="xsd:dateTime" use="required" />
     <xsd:anyAttribute processContents="lax" />
    </xsd:complexType>
  </xsd:element>

    <xsd:complexType name="any_complex_type">
        <xsd:complexContent>
            <xsd:restriction base="xsd:anyType">
                <xsd:sequence>
                    <xsd:any minOccurs="0" maxOccurs="unbounded" processContents="lax"/>
                </xsd:sequence>
                <xsd:anyAttribute processContents="lax" />
            </xsd:restriction>
        </xsd:complexContent>
    </xsd:complexType>
</xsd:schema>';

go 

我构建的结构类型示例如下:

declare @test [xml]([chamomile].[xsc_test_stack]) = N'
     <chamomile:test_stack xmlns:chamomile="https://github.com/KELightsey/chamomile" name="[chamomile].[person_test].[get_age]" test_count="2" pass_count="2" timestamp="2018-06-24T15:50:19.3466667">
       <description>This test stack consists of tests which validate the functionality of the age calculation for a person.</description>
     </chamomile:test_stack>';
go

declare @test [xml]([chamomile].[xsc_test_stack]) = N'
     <chamomile:test_stack xmlns:chamomile="https://github.com/KELightsey/chamomile" name="[chamomile].[person_test].[get_age]" test_count="2" pass_count="2" timestamp="2018-06-24T15:50:19.3466667">
       <description>This test stack consists of tests which validate the functionality of the age calculation for a person.</description>
       <test_stack_detail>
          <any_valid_xml_goes_here />
       </test_stack_detail>
     </chamomile:test_stack>';
go

我尝试过的是:

set @test_stack.modify(N'replace value of (//@test_count)[1] with sql:variable("@count")');

返回:Msg 9306, Level 16, State 1, Line 28 XQuery [modify()]: 'replace value of' 的目标不能是联合类型,找到 '(attribute(test_count,xs:int) | attribute(test_count,xs:anySimpleType)) ?'。

set @test_stack.modify(N'declare namespace chamomile="https://github.com/KELightsey/chamomile"; 
    replace value of (chamomile:test_stack/@test_count)[1] with sql:variable("@count")');

返回:Msg 9306, Level 16, State 1, Line 25 XQuery [modify()]: 'replace value of' 的目标不能是联合类型,找到 '(attribute(test_count,xs:int) | attribute(test_count,xs:anySimpleType)) ?'。

我花了几个小时在 Google 上挖掘这个。无类型 XML 的示例有很多很多,而有类型 XML 的一些示例仍然会抛出相同的异常。

我会很感激一些见解。

谢谢, 凯瑟琳

【问题讨论】:

    标签: tsql xquery-sql


    【解决方案1】:

    我必须承认,我也没有找到任何直接的方法。似乎是一个错误,至少我认为这没有任何意义。解决方法是一个简单的转换,但这与您在初始行中描述的解决方法非常接近:

    declare @test [xml]([chamomile].[xsc_test_stack]) = 
    N'<chamomile:test_stack xmlns:chamomile="https://github.com/KELightsey/chamomile" name="[chamomile].[person_test].[get_age]" test_count="2" pass_count="2" timestamp="2018-06-24T15:50:19.3466667">
           <description>This test stack consists of tests which validate the functionality of the age calculation for a person.</description>
         </chamomile:test_stack>';
    
    DECLARE @cnt INT=99;
    
    DECLARE @intermediate XML=CAST(@test AS XML); --magic happens here
    SET @intermediate.modify('declare namespace chamomile="https://github.com/KELightsey/chamomile"; 
                              replace value of (chamomile:test_stack/@test_count)[1] with sql:variable("@cnt")');
    
    SET @test=@intermediate; --re-assign to typed XML
    
    SELECT @test;
    

    【讨论】:

    • 我接受这个作为答案,因为我认为你是对的;这是一个错误。我将继续使用非类型化构建器,然后将其设置为类型化输出。谢谢你看看它Shnugo!
    • 我不能放过这个。我已将其追踪到“”。我从docs.microsoft.com/en-us/sql/t-sql/xml/… 开始,它确实替换了类型化 xml 中的属性值,并且一直在逐渐消失,直到我想出这是奇怪错误的根源。我会在几天后发布修改后的代码和示例。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-19
    • 2011-04-20
    • 1970-01-01
    相关资源
    最近更新 更多