我有以下内容:
declare @xml XML
SET @xml = '<record priref="2" creation="2009-12-14T10:39:04">
<field tag="aa" occ="1" lang="nl-NL">somedata</field>
<field tag="bb" occ="1" lang="en-US">somedata</field>
<field tag="bb" occ="2" lang="en-US">somedata</field>
<field tag="cc" occ="1">testdata</field>
<field tag="dd" occ="1">testdata</field>
<field tag="ee" occ="1" lang="nl-NL">somedata</field>
<field tag="ee" occ="1" lang="en-US">somedata</field>
</record>'
DECLARE @nodeCount int
DECLARE @i int
SET @i = 1
SELECT @nodeCount = @xml.value('count(/record/field/@lang)','varchar(5)')
WHILE (@i <= @nodeCount)
BEGIN
Set @xml.modify('replace value of (/record/field/@lang)[.="en-US"][1] with "nl-NL"')
SET @i = @i + 1
END
SELECT @xml
我想有条件地更新属性@lang。
如果“tag”和“occ”(如tag = ee)的节点具有相同的属性值组合,则@lang的属性值必须保持不变。
在其他情况下,它必须像上面的查询一样改变:将'en-US'改为'nl-NL'。
任何人都知道如何做到这一点?提前谢谢!
答案 0 :(得分:0)
这应该这样做
DECLARE @xml XML;
SET @xml = '<record priref="2" creation="2009-12-14T10:39:04">
<field tag="aa" occ="1" lang="nl-NL">somedata</field>
<field tag="bb" occ="1" lang="en-US">somedata</field>
<field tag="dd" occ="1">testdata</field>
<field tag="bb" occ="2" lang="en-US">somedata</field>
<field tag="cc" occ="1">testdata</field>
<field tag="ee" occ="1" lang="nl-NL">somedata</field>
<field tag="ee" occ="1" lang="en-US">somedata</field>
</record>'
DECLARE @no INT;
DECLARE @updneeded INT;
DECLARE nodecur CURSOR LOCAL FAST_FORWARD
FOR
SELECT rn,
CASE WHEN COUNT(1) OVER ( PARTITION BY tag, occ ) > 1 THEN 0
ELSE 1
END updneeded
FROM ( SELECT ROW_NUMBER() OVER ( ORDER BY node ) AS rn,
node.value('@tag', 'NVARCHAR(MAX)') AS tag,
node.value('@occ', 'NVARCHAR(MAX)') AS occ
FROM @xml.nodes('/record/field') x ( node )
) X;
OPEN nodecur;
WHILE ( 1 = 1 )
BEGIN
FETCH NEXT FROM nodecur INTO @no, @updneeded;
IF ( @@FETCH_STATUS <> 0 ) BREAK;
IF ( @updneeded = 1 )
SET @xml.modify('replace value of (/record/field[sql:variable("@no")]/@lang)[.="en-US"][1] with "nl-NL"');
END
CLOSE nodecur;
DEALLOCATE nodecur;
SELECT @xml;
然而,SQL对这些类型的操作并不是很快。在应用程序代码中执行此操作或将一些CLR功能放在一起可能更有效。