使用条件

时间:2018-01-22 07:54:05

标签: sql sql-server xml xml.modify

希望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>')

我需要有条件地更换“已批准出版”&#39;值为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 

2 个答案:

答案 0 :(得分:1)

最后,根据Shnugo的反馈结果,下面结束了工作,谢谢!对我来说,理解XQUERY好一点是一个巨大的帮助!!

我需要更新SQL中的XML类型列内容,以下是我在我使用的旧遗留系统中批量修改值的整体解决方案的一部分所需的基本工作。我确定有一个更优雅的解决方案,但我必须设置一个带有xml特殊字符的变量来保留列本身的字符串文字 - 由于某种原因我不能让它在排队后工作&#39;然后&#39; 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

批准发布后的XML输出&#39;价值设定为&#39; F&#39;来自&#39; T&#39;保留特殊的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>

答案 1 :(得分:0)

新答案

xml特殊字符&#xA;&#xD; 只不过是新行换行符(LF)< / em>和回车(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>

OMSBMS之间的新行仍然采用此方法。

以前的回答

首先是一些评论/问题?

  • 为什么需要将其转换为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>