3

我在 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 apply做一个modify-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 业务逻辑中。

4

1 回答 1

1

您不能modify在 select 语句中使用。

来自modify() 方法(xml 数据类型)

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

我认为你有两个选择。

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

如果选择第二个选项,则必须使用 while 循环,因为插入(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
于 2012-09-05T17:04:29.880 回答