1

希望 XML 专家能快速回答一个问题。我有一个带有 XML 类型列的下表,其中包含以下 XML 架构和一条记录中的数据:

INSERT INTO XMLTEST (testXML)
values ('<R>
  <P N="Status" V="&#xD;&#xA;Draft&#xD;&#xA;" />
  <P N="Approved For Publishing" V="&#xD;&#xA;T&#xD;&#xA;" />
  <P N="Concealed From Publishing" V="&#xD;&#xA;F&#xD;&#xA;" />
  <P N="Management System" V="&#xD;&#xA;OMS&#xD;&#xA;BMS&#xD;&#xA;" />
</R>')

我需要有条件地将“已批准发布”值替换为 F,我认为最好的方法是在更改 V 值之前先检查 xml 行的 N 值名称。我一直试图让下面的 SQL 工作,但没有运气。有人可以帮忙指出什么问题吗?

DECLARE @myDoc xml
SET @myDoc = (SELECT TOP 1 CAST(testXML AS VARCHAR(MAX)) FROM XMLTEST) 
Select @myDoc
SET @myDoc.modify('  
  replace value of (/R/P/@V)[1]  
  with (  
       if (/R/P/N = ''Approved For Publishing'') then  
         "F"  
       else  
          "T"  
      )  
')  
SELECT @myDoc 
4

2 回答 2

1

最后,根据Shnugo的反馈,下面的工作结束了,谢谢!这对我更好地理解 XQUERY 帮助很大!

我需要在 SQL 中更新 XML 类型的列内容,下面是我在使用的旧遗留系统中批量修改值的整体解决方案所需的基本工作部分。我确信有一个更优雅的解决方案,但我必须使用 xml 特殊字符设置一个变量以将字符串文字保留在列本身中 - 由于某种原因,我无法在“then”之后使其正常工作if 块的一部分。

我还对其进行了更改,使其仅修改命中条件检查的值并为其余部分保留相同的数据。

DECLARE @myDoc xml
SET @myDoc = (SELECT TOP 1 testXML FROM XMLTEST) 
UPDATE XMLTEST
SET testXML = (SELECT @myDoc.query(
N'
    <R>
    {
    let $str := "&#xD;&#xA;F&#xD;&#xA;"
    for $p in /R/P
    return
    if($p/@N="Approved For Publishing") then
     <P N="{$p/@N}" V="{$str}"/>
    else
     <P N="{$p/@N}" V="{$p/@V}"/>
    }
    </R>
'))
SELECT * FROM XMLTEST

将“已批准发布”值从“T”设置为“F”后的 XML 输出,保留特殊的 XML 字符。

<R>
  <P N="Status" V="&#xD;&#xA;Draft&#xD;&#xA;" />
  <P N="Approved For Publishing" V="&#xD;&#xA;F&#xD;&#xA;" />
  <P N="Concealed From Publishing" V="&#xD;&#xA;F&#xD;&#xA;" />
  <P N="Management System" V="&#xD;&#xA;OMS&#xD;&#xA;BMS&#xD;&#xA;" />
</R>
于 2018-01-23T03:26:03.163 回答
0

新答案

xml 特殊字符&#xA;&#xD;只不过是一个新行(换行符(LF)和回车CR )。我不认为这应该真正存在XML 的价值范围内。换行应该添加到您的表示层中。

以下代码显示了如何在不需要变量或任何强制转换的情况下更新表格的方式。

DECLARE @tbl TABLE(ID INT IDENTITY, testXML XML);
INSERT INTO @tbl (testXML)
values ('<R>
  <P N="Status" V="&#xD;&#xA;Draft&#xD;&#xA;" />
  <P N="Approved For Publishing" V="&#xD;&#xA;T&#xD;&#xA;" />
  <P N="Concealed From Publishing" V="&#xD;&#xA;F&#xD;&#xA;" />
  <P N="Management System" V="&#xD;&#xA;OMS&#xD;&#xA;BMS&#xD;&#xA;" />
</R>')
,('<R>
  <P N="Status" V="&#xD;&#xA;Draft&#xD;&#xA;" />
  <P N="Approved For Publishing" V="&#xD;&#xA;T&#xD;&#xA;" />
  <P N="Concealed From Publishing" V="&#xD;&#xA;F&#xD;&#xA;" />
  <P N="Management System" V="&#xD;&#xA;OMS&#xD;&#xA;BMS&#xD;&#xA;" />
</R>');

UPDATE @tbl SET testXML=testXML.query(
                                    N'
                                        <R>
                                        {
                                        for $p in /R/P
                                        return
                                        if($p/@N="Approved For Publishing") then
                                         <P N="{$p/@N}" V="F"/>
                                        else
                                         <P N="{$p/@N}" V="{substring($p/@V,3,string-length($p/@V)-4)}"/>
                                        }
                                        </R>
                                    ');
SELECT * FROM @tbl;

操作后其中一个 XML 将如下所示:

<R>
  <P N="Status" V="Draft" />
  <P N="Approved For Publishing" V="F" />
  <P N="Concealed From Publishing" V="F" />
  <P N="Management System" V="OMS&#xD;&#xA;BMS" />
</R>

这种方法之间的新界限OMS仍然BMS存在。

上一个答案

先发表一些评论/问题?

  • 为什么您需要将其转换为VARCHAR(MAX)然后再转换为XML(隐式)?
  • 您需要更新表中的值还是临时操作?
  • 您不能一次更新多个值.modify()...
  • 如果您处理 XML,您应该始终使用!NVARCHAR
  • 是否需要变量@myDoc

您可以尝试使用FLWOR XQuery

DECLARE @tbl TABLE(testXML XML);
INSERT INTO @tbl (testXML)
values ('<R>
  <P N="Status" V="&#xD;&#xA;Draft&#xD;&#xA;" />
  <P N="Approved For Publishing" V="&#xD;&#xA;T&#xD;&#xA;" />
  <P N="Concealed From Publishing" V="&#xD;&#xA;F&#xD;&#xA;" />
  <P N="Management System" V="&#xD;&#xA;OMS&#xD;&#xA;BMS&#xD;&#xA;" />
</R>');

DECLARE @myDoc xml
SET @myDoc = (SELECT TOP 1 CAST(testXML AS VARCHAR(MAX)) FROM @tbl) 

SELECT @myDoc.query(
N'
    <R>
    {
    for $p in /R/P
    return
    if($p/@N="Approved For Publishing") then
     <P N="{$p/@N}" V="F"/>
    else
     <P N="{$p/@N}" V="T"/>
    }
    </R>
')

结果

<R>
  <P N="Status" V="T" />
  <P N="Approved For Publishing" V="F" />
  <P N="Concealed From Publishing" V="T" />
  <P N="Management System" V="T" />
</R>
于 2018-01-22T08:07:43.290 回答