0

我的数据库中有几个 XML 需要更新。这是它们的简单表示:

<root>
  <child1>blah</child1>
</root>

我需要<child1>用另一个元素包装以获得这样的结构:

<root>
  <child1Root>
    <child1>blah</child1>
  </child1Root>
</root>

看起来很简单,但我不是 T-SQL 和 DML 专家。

注意:如果有人想知道为什么要更新,答案是下面的 XML 不能使用 DataContractSerializer 反序列化。它可以使用 XmlSerializer 和 XmlArray 属性进行反序列化,但不能使用 DCS:

<root>
  <child1>blah</child1>
  <child2>blah</child2>
</root>
4

3 回答 3

2

如果您的实际代码与您的示例一样简单,那么您可以这样做:

DECLARE @yourTable TABLE ( yourXML XML )

INSERT INTO @yourTable ( yourXML )
VALUES 
    ( '<root><child1>blah1</child1></root>' ),
    ( '<root><child1>blah2</child1></root>' )

UPDATE @yourTable
SET yourXML = yourXML.query('root/child1').query('<root><child1Root>{.}</child1Root></root>') 

SELECT * FROM @yourTable

如果您的真实 XML 有点复杂,那么您可能需要将其分解。

于 2012-09-18T13:32:36.580 回答
0

蛮力方法:

DECLARE @myDoc xml       
SET @myDoc = '
<root>       
    <child1>blah</child1>       
</root>'       
SELECT @myDoc       

DECLARE @child1 xml;
SET @child1 = @myDoc.query('/root/child1')
SELECT @child1

SET @myDoc.modify('       
insert <child1Root />
into (/root)[1]') 
SELECT @myDoc       

SET @myDoc.modify('       
insert sql:variable("@child1")
into (/root/child1Root)[1]') 
SELECT @myDoc       

SET @myDoc.modify('       
delete /root/child1') 
SELECT @myDoc       
于 2012-09-17T21:42:59.890 回答
0

这是一个工作示例。鉴于有效的 XML 具有严格的规则,我想不出字符串操作不起作用的原因。至少,作为字符串搜索关键的“<”不应该存在于 XML 标记名称之外。

-- create a sample table variable with a few variations
declare @T table (sample xml)
insert @T select '
<root>
  <child1>blah</child1>
</root>'
insert @T select '
<root>
  <child1>blah1</child1>
  <child1>blah2</child1>
</root>'
insert @T select '
<root>
  <child1>
    blah1
    <child2>blah2</child2>
  </child1>
</root>'
insert @T select '
<root>
<child0>
  <child1>
    <child4>
      <child3>blah2</child3>
    </child4>
  </child1>
</child0>
</root>'

-- peek at the content
select * from @T

-- perform the replacements as many times as required
-- note that the string "stackoverflow123" is expected to NEVER
--    exist in your data, or use another string if it does!
while @@rowcount > 0
begin
    update T
    set sample = stuff(X.A, Y.B, Z.C - Y.B + 9, '<child1Root>'+
        replace(replace(
            SUBSTRING(X.A, Y.B, Z.C - Y.B + 9),
            '<child1>','<stackoverflow123>'),
            '</child1>','</stackoverflow123>')
                +'</child1Root>')
    from @T T
    cross apply (
        select convert(varchar(max),sample)) X(A)
    cross apply (
        select patindex('%<child1>%</child1>%', X.A)) Y(B)
    cross apply (
        select charindex('</child1>', X.A, Y.B+1)) Z(C)
    where Z.C > 0
end

-- finally revert the placeholder string back to "child1"
update @T
set sample = replace(convert(varchar(max),sample), 'stackoverflow123', 'child1')

-- inspect the finished product
select * from @T
于 2012-09-18T02:25:04.040 回答