2

说,我有一个看起来像这样的 xml 列:

<mi>
  <m>42</m>
</mi>

假设表:

Word(WordId:bigint, Wordtext:nvarchar, MessageIndex:xml)

如果 @MessageId 已经存在于 Messageindex 的 xml 树中的某个位置,我不希望以下参数化查询插入新的 xml 节点,而是要么失败并出现确定性错误代码,要么静默:

begin try
    insert into Word (WordText, MessageIndex) values (@WordText, '<mi></mi>');
    update Word set MessageIndex.modify('insert (<m>{sql:variable(""@MessageId"")}</m>) into(/mi)[1]') where WordId = scope_identity();
end try
begin catch
    if error_number() = 2627
    begin
        update Word set
            MessageIndex.modify('insert (<m>{sql:variable(""@MessageId"")}</m>) into(/mi)[1]')
        where
            WordText = @WordText;
    end
    else
        throw
end catch

从 Word 中选择 WordId,其中 WordText = @WordText;

我如何有效地做到这一点?

4

2 回答 2

3

像这样的东西适合你吗?

DECLARE @Word TABLE (WordId bigint identity, Wordtext NVARCHAR(20), MessageIndex xml ) 

insert into @word ( messageIndex )
select '<mi> 
  <m>42</m> 
</mi>'

DECLARE @WordText NVARCHAR(20) = 'wordText'
DECLARE @messageId INT = 42

begin try 

    if exists ( select 1 from @Word where MessageIndex.exist('//mi[.=sql:variable("@MessageId")]') = 0 )
    begin
        insert into @Word (WordText, MessageIndex) values (@WordText, '<mi></mi>'); 

        update @Word set MessageIndex.modify('insert <m>{sql:variable("@MessageId")}</m> into (mi)[1]') 
        where WordId = scope_identity(); 

    end
    --else
        -- do something here?

end try 
begin catch 
    if error_number() = 2627 
    begin 
        update @Word set MessageIndex.modify('insert <m>{sql:variable("@MessageId")}</m> into (mi)[1]') 
        where WordText = @WordText; 
    end 
    else 
        throw 
end catch 

select * from @Word
于 2012-09-19T00:12:10.893 回答
2

这是一篇较旧的帖子,但我想分享我的解决方案,当元素存在存在时适用:

首先,当元素(varchar 类型)存在时,我们需要更新:

UPDATE PD 
SET  
[ValuesXml].modify('replace value of
(/Employee/KeyValue/text())[1] with (sql:column("x.KeyValue"))')
FROM Pdetail PD  
INNER JOIN TableXml x ON PD.PId = x.PId 
WHERE PD.[ValuesXml].exist('/Employee/KeyValue') = 1

其次,我们需要在元素不存在时插入:

UPDATE PD
SET 
[ValuesXml].modify(
'insert <KeyValue>{sql:column("x.KeyValue")}</KeyValue> into (/Employee)[1]')
FROM RK.Pdetail PD 
INNER JOIN TableXml x ON PD.PId = x.PId 
WHERE PD.[ValuesXml].exist('/Employee/KeyValue') = 0  

如果您需要使用 XML 中的多个实体实例,则需要使用 CROSS APPLY 并删除 [1] 单例指示器。

于 2017-09-14T17:11:46.223 回答