【问题标题】:Update XML field with no text in T-SQL在 T-SQL 中更新没有文本的 XML 字段
【发布时间】:2011-06-06 15:51:46
【问题描述】:

我在更新 SQL 字段时遇到了一个问题,因为我编写的内容对于存在文本的 xml 节点非常有效,但是当节点为空时它会跳闸。

<filemeta filetype="Video">
  <heading>TEST</heading>
  <description />
</filemeta>

这段代码运行良好;

UPDATE filemetaDB SET filemeta.modify('replace value of (/filemeta/heading/text())[1] with "TEST"');

但是这会中断;

UPDATE filemetaDB SET filemeta.modify('replace value of (/filemeta/description/text())[1] with "notworking!"');

感谢您的帮助。

【问题讨论】:

    标签: tsql sql-server-2008 xquery-sql


    【解决方案1】:

    此节点(/filemeta/description/text())[1] 在 XML 中不存在,因此无需替换。您必须改为进行插入。如果您有一个混合了空节点和具有值的节点的场景,您必须运行两个更新语句。

    declare @filemetaDB table(filemeta xml)
    
    insert into @filemetaDB values
    ('<filemeta><description>Not empty</description></filemeta>'), -- Not empty node
    ('<filemeta><description/></filemeta>'),                       -- Empty node
    ('<filemeta></filemeta>')                                      -- Missing node
    
    -- Replace value for nodes with value
    update @filemetaDB
    set filemeta.modify('replace value of (/filemeta/description/text())[1] with "TEST 1"')
    where filemeta.exist('/filemeta/description/text()') = 1
    
    -- Add text node for empty nodes
    update @filemetaDB
    set filemeta.modify('insert text{"TEST 2"} into (/filemeta/description)[1]')
    where filemeta.exist('/filemeta/description/text()') = 0
    
    select *
    from @filemetaDB
    

    结果:

    filemeta
    ------------------------------------------------------
    <filemeta><description>TEST 1</description></filemeta>
    <filemeta><description>TEST 2</description></filemeta>
    <filemeta />
    

    【讨论】:

    • 如何在 modify 方法内的 INSERT 语句中使用变量?
    • @SiKni8 看看使用sql:variable("")
    • 试过这个:Set @xml.modify('insert xs:string(sql:variable("@locAnchor")) into (/root/StartOne/Value6)[1]'); 我一直收到错误:XQuery [modify()]: Only non-document nodes can be inserted. Found "xs:string ?".
    • @SiKni8 试试这个set @xml.modify('insert text{sql:variable("@LocAnchor")} into (/root/StartOne/Value6)[1]');
    • 非常不幸。 :-) 这在 2018 年仍然如此,还是有改进?我在the replace docs 中没有看到任何暗示有,但是...
    【解决方案2】:

    我有一个场景,我只想更新 EMPTY 节点。

    UPDATE filemetaDB SET filemeta.modify('
        insert text{"Oh, this works!!"}
        into (/filemeta/description[not(node()) and not(text())])[1]
    ');
    

    not(node()) 表示没有子项,not(text()) 表示没有文本内容(但可能有子项,因此请根据需要混合和匹配这些情况)

    【讨论】:

    • 非常方便,这样可以节省执行存在检查的时间。
    【解决方案3】:

    你可以在更新前检查节点是否有Data如:

    IF EXISTS(
                SELECT  null
                FROM    filemetaDB
                WHERE   cast(filemeta.query('if (/filemeta/description[1]) then "T" else ""') as varchar) = 'T')
        BEGIN
            UPDATE filemetaDB SET filemeta.modify('replace value of (/filemeta/description/text())[1] with "notworking!"');
        END
    

    【讨论】:

      【解决方案4】:

      我认为这种方法不适用于空节点。
      您也可以检查此标题:link

      【讨论】:

        猜你喜欢
        • 2011-03-09
        • 1970-01-01
        • 2010-09-22
        • 2018-08-31
        • 2014-07-29
        • 1970-01-01
        • 2021-04-13
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多