我的数据库中有几个需要更新的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>
答案 0 :(得分: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稍微复杂一些,那么您可能需要将其分解。
答案 1 :(得分: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
答案 2 :(得分:0)
这是一份工作样本。鉴于有效的XML具有严格的规则,我认为没有理由为什么字符串操作不起作用。至少,“&lt;”这是字符串搜索的关键,不应该存在于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