在 SQL 服务器 table 中键入 XML 更新

Typed XML Update in SQL Server table

我有第 3 方 table 和 XML 列,如果 key\string = 'recipient'。这是原始 XML 的一部分,包含 2 个项目:

DECLARE @myDoc XML  
SET @myDoc = '<Root>
<item>
    <key>
      <string>subject</string>
    </key>
    <value>
      <anyType xmlns:q1="http://www.w3.org/2001/XMLSchema" xmlns:p5="http://www.w3.org/2001/XMLSchema-instance" p5:type="q1:string">test subject</anyType>
    </value>
  </item>
<item>
    <key>
      <string>recipient</string>
    </key>
    <value>
      <anyType xmlns:q1="http://www.w3.org/2001/XMLSchema" xmlns:p5="http://www.w3.org/2001/XMLSchema-instance" p5:type="q1:string">prodops@company.com</anyType>
    </value>
  </item>
</Root>'  
  
SET @myDoc.modify('  
  declare namespace q1="http://www.w3.org/2001/XMLSchema"; declare namespace p5="http://www.w3.org/2001/XMLSchema-instance";    
  replace value of (/q1:Root/q1:item/q1:value/p5:type="q1:string")[1]  
  with ("devops@company.com")  
')  
SELECT @myDoc

我有点黑了我的方式到这一点 - XML 不是我的强项。基于 BOL,我需要在 modify()?正确的?我确定我缺少一个 if 语句,但对于如何为收件人取消引用该值只是一个谜。以前有人这样做过——我敢肯定。目标是在刷新生产数据后合并到 post-restore 脚本中进行测试。

请注意,这会按原样失败

Msg 2337, Level 16, State 1, Line 125 XQuery [modify()]: The target of 'replace' must be at most one node, found 'xs:boolean ?'"

您需要指定text()来替换节点的内部文本。您还需要引用anyType节点,您没有.

从表面上看,none 个相关节点实际上使用了命名空间,因此我们根本不需要它们。

SET @myDoc.modify('  
  replace value of (/Root/item[key[string[text()="recipient"]]]/value/anyType/text())[1]  
  with ("devops@company.com")  
');

解释:

  • 下降到 /Root,不需要命名空间
  • 使用谓词下降到 /item[...
  • ... 必须有 key[ 个节点 ...
  • ... 有 string[ 个节点 ...
  • ... 内部有 text()="recipient"]]]
  • 回到原来的item我们下降/value然后/anyType然后内部/text()
  • 所有括起来到[1]以确保单个节点

问题的标题指定“在 SQL 服务器 table 中键入 XML 更新”。

所提供的 XML 不受任何 XSD 架构的约束。这就是为什么不输入 XML 的原因。一个真正类型的 XML 更新不同。

请尝试以下解决方案。它具有以下内容:

  • 更简单的 XPath 谓词表达式。
  • 使用 SQL 变量作为新值。

所有功劳归功于@Charlieface。

SQL

DECLARE @myDoc XML =
N'<Root>
    <item>
        <key>
            <string>subject</string>
        </key>
        <value>
            <anyType xmlns:q1="http://www.w3.org/2001/XMLSchema"
                     xmlns:p5="http://www.w3.org/2001/XMLSchema-instance"
                     p5:type="q1:string">test subject</anyType>
        </value>
    </item>
    <item>
        <key>
            <string>recipient</string>
        </key>
        <value>
            <anyType xmlns:q1="http://www.w3.org/2001/XMLSchema"
                     xmlns:p5="http://www.w3.org/2001/XMLSchema-instance"
                     p5:type="q1:string">prodops@company.com</anyType>
        </value>
    </item>
</Root>';

DECLARE @anyType VARCHAR(30) = 'devops@company.com';
  
SET @myDoc.modify('  
  replace value of (/Root/item[key/string/text()="recipient"]/value/anyType/text())[1]  
  with (sql:variable("@anyType"))  
');

-- test 
SELECT @myDoc;