Woj*_*teq 11 xml sql-server xquery
我有一XML列包含具有类似结构的数据:
<Root>
<Elements>
<Element Code="1" Value="aaa"></Element>
<Element Code="2" Value="bbb"></Element>
<Element Code="3" Value="ccc"></Element>
</Elements>
</Root>
Run Code Online (Sandbox Code Playgroud)
如何使用 SQL Server 修改数据以将每个Value属性更改为元素?
<Root>
<Elements>
<Element Code="1">
<Value>aaa</Value>
</Element>
<Element Code="2">
<Value>bbb</Value>
</Element>
<Element Code="3">
<Value>ccc</Value>
</Element>
</Elements>
</Root>
Run Code Online (Sandbox Code Playgroud)
更新:
我的 XML 看起来更像这样:
<Root attr1="val1" attr2="val2">
<Elements>
<Element Code="1" Value="aaa" ExtraData="extra" />
<Element Code="2" Value="bbb" ExtraData="extra" />
<Element Code="3" Value="ccc" ExtraData="extra" />
<Element Code="4" Value="" ExtraData="extra" />
<Element Code="5" ExtraData="extra" />
</Elements>
<ExtraData>
<!-- Some XML is here -->
</ExtraData>
</Root>
Run Code Online (Sandbox Code Playgroud)
我只想移动Value属性并保留所有其他属性和元素。
Mik*_*son 13
您可以分解 XML 并使用 XQuery 再次重建它。
declare @X xml = '
<Root attr1="val1" attr2="val2">
<Elements>
<Element Code="1" Value="aaa" ExtraData="extra" />
<Element Code="2" Value="" ExtraData="extra" />
<Element Code="3" ExtraData="extra" />
</Elements>
<ExtraData>
<!-- Some XML is here -->
</ExtraData>
</Root>';
select @X.query('
(: Create element Root :)
element Root
{
(: Add all attributes from Root to Root :)
/Root/@*,
(: create element Elements under Root :)
element Elements
{
(: For each Element element in /Root/Elements :)
for $e in /Root/Elements/Element
return
(: Add element Element :)
element Element
{
(: Add all attributes except Value to Element :)
$e/@*[local-name() != "Value"],
(: Check if Attribute Value exist :)
if (data($e/@Value) != "")
then
(: Create a Value element under Element :)
element Value
{
(: Add attribute Value as data to the element Element :)
data($e/@Value)
}
else () (: Empty element :)
}
},
(: Add all childelements to Root except the Elements element :)
/Root/*[local-name() != "Elements"]
}');
Run Code Online (Sandbox Code Playgroud)
结果:
<Root attr1="val1" attr2="val2">
<Elements>
<Element Code="1" ExtraData="extra">
<Value>aaa</Value>
</Element>
<Element Code="2" ExtraData="extra" />
<Element Code="3" ExtraData="extra" />
</Elements>
<ExtraData>
<!-- Some XML is here -->
</ExtraData>
</Root>
Run Code Online (Sandbox Code Playgroud)
如果Elements不是Root查询下的第一个元素需要修改为添加Elements第一个之前的所有元素和之后的所有元素Elements。
您还可以使用 XML 数据类型的方法(例如modify)和一些 XQuery 来修改 xml,例如
DECLARE @x XML = '<Root attr1="val1" attr2="val2">
<Elements>
<Element Code="1" Value="aaa" ExtraData="extra" />
<Element Code="2" Value="bbb" ExtraData="extra" />
<Element Code="3" Value="ccc" ExtraData="extra" />
</Elements>
<ExtraData>
<!-- Some XML is here -->
</ExtraData>
</Root>'
SELECT 'before' s, DATALENGTH(@x) dl, @x x
-- Add 'Value' element to each Element which doesn't already have one
DECLARE @i INT = 0
WHILE @x.exist('Root/Elements/Element[not(Value)]') = 1
BEGIN
SET @x.modify( 'insert element Value {data(Root/Elements/Element[not(Value)]/@Value)[1]} into (Root/Elements/Element[not(Value)])[1]' )
SET @i += 1
IF @i > 99 BEGIN RAISERROR( 'Too many loops...', 16, 1 ) BREAK END
END
-- Now delete all Value attributes
SET @x.modify('delete Root/Elements/Element/@Value' )
SELECT 'after' s, DATALENGTH(@x) dl, @x x
Run Code Online (Sandbox Code Playgroud)
这种方法往往不能很好地扩展大型 XML 片段,但可能比批量替换 XML 更适合您。
如果您的 XML 存储在表中,您也可以轻松地调整此方法。再次根据经验,我不建议对百万行表运行单个更新。如果您的表很大,请考虑通过它运行游标或以其他方式批量更新。这是技术:
DECLARE @t TABLE ( rowId INT IDENTITY PRIMARY KEY, yourXML XML )
INSERT INTO @t ( yourXML )
SELECT '<Root attr1="val1" attr2="val2">
<Elements>
<Element Code="1" Value="aaa" ExtraData="extra" />
<Element Code="2" Value="bbb" ExtraData="extra" />
<Element Code="3" Value="ccc" ExtraData="extra" />
</Elements>
<ExtraData>
<!-- Some XML is here -->
</ExtraData>
</Root>'
INSERT INTO @t ( yourXML )
SELECT '<Root attr1="val1" attr2="val2">
<Elements>
<Element Code="21" Value="uuu" ExtraData="extra" />
<Element Code="22" Value="vvv" ExtraData="extra" />
<Element Code="23" Value="www" ExtraData="extra" />
<Element Code="24" Value="xxx" ExtraData="extra" />
<Element Code="25" Value="yyy" ExtraData="extra" />
<Element Code="26" Value="zzz" ExtraData="extra" />
</Elements>
<ExtraData>
<!-- Some XML is here -->
</ExtraData>
</Root>'
SELECT 'before' s, DATALENGTH(yourXML) dl, yourXML
FROM @t
-- Add 'Value' element to each Element which doesn't already have one
DECLARE @i INT = 0
WHILE EXISTS ( SELECT * FROM @t WHERE yourXML.exist('Root/Elements/Element[not(Value)]') = 1 )
BEGIN
UPDATE @t
SET yourXML.modify( 'insert element Value {data(Root/Elements/Element[not(Value)]/@Value)[1]} into (Root/Elements/Element[not(Value)])[1]' )
SET @i += 1
IF @i > 99 BEGIN RAISERROR( 'Too many loops...', 16, 1 ) BREAK END
END
-- Now delete all Value attributes
UPDATE @t
SET yourXML.modify('delete Root/Elements/Element/@Value' )
SELECT 'after' s, DATALENGTH(yourXML) dl, yourXML
FROM @t
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
3290 次 |
| 最近记录: |