【问题标题】:Typed XML Update in SQL Server tableSQL Server 表中的类型化 XML 更新
【发布时间】:2021-05-03 21:00:18
【问题描述】:

我有带有 XML 列的 3rd 方表,如果 key\string = 'recipient',我需要更改 value 中的收件人值。这是原始 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 语句,但这只是一个关于如何为收件人取消引用该值的谜团。以前有人这样做过——我敢肯定。目标是在刷新生产数据后合并到恢复后脚本中进行测试。

请注意,这会失败

消息 2337,第 16 级,状态 1,第 125 行 XQuery [modify()]: 'replace' 的目标最多只能是一个节点,找到 'xs:boolean ?'"

【问题讨论】:

    标签: sql-server xml namespaces xquery updates


    【解决方案1】:

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

    从表面上看,没有一个相关节点真正使用命名空间,所以我们根本不需要它们。

    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] 以确保单个节点

    【讨论】:

    • 查理脸——你现在是神!我以前在节点上做过一些 xquery,但这在我的桌子上做,我根本没有时间深入研究这个。我想你刚刚救了我几天。
    【解决方案2】:

    问题的标题指定“SQL Server 表中的类型化 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;
    

    【讨论】:

    • 感谢 Yitzhak - 很高兴能像您一样将所有内容放在一起。我希望这对其他人也有帮助。我在 SO 上找不到这样的确切问题。大多数是标准 xml 和 BOL 等中的答案。
    猜你喜欢
    • 2018-12-04
    • 2012-05-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多