【问题标题】:SQL - Fetch XML with an INNER JOIN, modifying the XMLSQL - 使用 INNER JOIN 获取 XML,修改 XML
【发布时间】:2012-09-04 12:46:32
【问题描述】:

我在 SQL Server 2008 中有一个将 XML 数据存储在 XML 列中的表。一个典型的 XML 片段是:

<validation>
    <Field1 author="56234" date="20120101" />
    <Field2 author="23232" date="20120101" />
        [...etc...]
</validation>

我正在尝试解决的问题 - 我不知道该怎么做 - 使用 INNER JOIN 选择此数据到另一个表并修改结果集中的 XML 数据,即,我得到这个:

<validation>
    <Field1 author="56234" date="20120101" authorFullName="Bob Smith" />
    <Field2 author="23232" date="20120101" authorFullName="Jane Hill" />
        [...etc...]
</validation>

现在我知道我可以使用CROSS APPLY 将 XML 数据直接拉入记录集并进行内部连接 ​​- 例如:

select xmldata.a, people.personname
    from xmldata
        cross apply xmldata.x.nodes('/validation/node()') vdata(fielddata)
        inner join people 
            on people.personid = vdata.fielddata.value('@author','NVARCHAR(20)')

但我真正想做的是返回原始 XML,但添加了一个新属性,将 people.PersonName 映射到新的 @authorFullName 属性。

我无法完全确定语法(或者即使确实有可能)。我假设我会 cross applymodify 一起做 insert attribute - 基于

select xmldata.a, xmldata.x
    from xmldata
        cross apply xmldata.x.modify('insert attribute authorFullName {sql:column("people.personfullname")} into /validation/node()')
        inner join people 
            on people.personid = [...what goes here?...]

但正确的语法让我无法理解。我越来越认为这是不可能的,我最好在两个查询中执行此操作并将结果合并到非 SQL 业务逻辑中。

【问题讨论】:

    标签: sql-server-2008 sqlxml


    【解决方案1】:

    您不能在选择语句中使用modify

    来自modify() Method (xml Data Type)

    xml数据类型的modify()方法只能在SET中使用 UPDATE 语句的子句。

    我认为你有两个选择。

    1. 分解 XML 并使用 for xml path 以您想要的方式重建 XML 文档并在适当的位置插入人名。
    2. 将 XML 提取到变量中并使用 set @XML.modify(insert... 插入人名。

    如果选择第二个选项,则必须使用 while 循环,因为 insert (XML DML) 中的表达式2 必须是单个节点。

    选项 2 的代码可能如下所示。

    declare @XML xml
    declare @C int
    declare @PersonName varchar(50)
    declare @PersonID int
    
    -- Store your XML in a XML variable
    set @XML = 
    '<validation>
        <Field1 author="56234" date="20120101" />
        <Field2 author="23232" date="20120101" />
    </validation>'
    
    -- Get number of nodes to be modified
    set @C = @XML.value('count(/validation/*)', 'int')
    
    -- For each node
    while @C > 0
    begin
      -- Get person id from XML
      set @PersonID = @XML.value('(/validation/*[sql:variable("@C")]/@author)[1]', 'int')
    
      -- Get person name
      select @PersonName = personname
      from people
      where personid = @PersonID 
    
      if @@rowcount = 1
      begin
        -- add person name to XML
        set @XML.modify('insert attribute authorFullName {sql:variable("@PersonName")} 
                            into (/validation/*[sql:variable("@C")])[1]')
      end
    
      -- next node
      set @C = @C - 1
    end
    

    【讨论】:

    • 我设法在文档中错过了这一点。显然花了很多时间盯着他们看。不过,在处理 XML 方面,考虑到 SQL 级别涉及的工作,我可能最好将单独的数据集拉回业务代码并在那里合并。不过感谢您的反馈...!
    猜你喜欢
    • 2021-10-18
    • 2023-03-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-08
    • 1970-01-01
    • 2017-01-02
    相关资源
    最近更新 更多