2012-08-09 70 views
4

是否可以在一個Update內修改單個節點上的多個屬性?立即更新sql server xml數據字段上的多個屬性

我有類似的東西:

<ENTITY NAME="entity1"> 
    <ATTR ID="attr1" CAPTION="Attributes to Change" SIZE="100" WIDTH="100"></ATTR> 
</ENTITY> 

我已經能夠使用三個單獨的更新修改標題,大小,和width屬性,但我已經看了白白爲某種方式結合起來他們到一個單一的更新。可能嗎?我已經使用了更新的

例子:

UPDATE t 
SET  [column_name].modify('replace value of (/ENTITY/ATTR/@CAPTION)[1] with "New Attribute Caption"') 
FROM  table t 

UPDATE t 
SET  [column_name].modify('replace value of (/ENTITY/ATTR/@SIZE)[1] with "200"') 
FROM  table t 

UPDATE t 
SET  [column_name].modify('replace value of (/ENTITY/ATTR/@WIDTH)[1] with "200"') 
FROM  table t 
+1

沒有,據我所知,有沒有辦法多個更新合併到一個XML列到一個單獨的語句。你有什麼作品 - 離開它。 – 2012-08-09 19:37:51

+0

可能重複[TSQL 2005,XML DML - 一次更新兩個值?](http://stackoverflow.com/questions/7327440/tsql-2005-xml-dml-update-two-values-at-once) – Yishai 2016-08-11 02:53:27

回答

3

不,這是不可能的。

replace value of (XML DML)

表達式1
標識其值被更新的節點。它必須 只標識一個節點。也就是說,Expression1必須是一個靜態 單身人士。

1

你確實有幾個選擇,但可能不會比你的三個更新更好。選項是1)重建XML或2)創建映射表。

XML的DML操作是昂貴,因此存在一個臨界點重建XML時可能更有效 - 這取決於你的XML的大小,多少的屬性被替換等

映射表解決方案使用循環,因此與三種更新解決方案類似。但是,您具有使數據驅動的優勢。

總之,要通過這個演示一下,讓我知道你上車:

USE tempdb 
GO 
SET NOCOUNT ON 

DECLARE @t TABLE (yourXML XML) 

INSERT INTO @t (yourXML) 
SELECT '<ENTITY NAME="entity1"> 
    <ATTR ID="attr1" CAPTION="Attributes to Change" SIZE="100" WIDTH="100"></ATTR> 
</ENTITY>' 


SELECT 'before' s, * FROM @t 

------------------------------------------------------------------------------------------------ 
-- Reconstruct the inner xml START 
------------------------------------------------------------------------------------------------ 

-- Delete current element and attributes 
UPDATE @t 
SET yourXML.modify('delete ENTITY[@NAME="entity1"]/ATTR') 

DECLARE @xml XML = '', @caption VARCHAR(100), @size INT, @width INT 

SELECT @caption = 'New Attribute Caption', @size = 200, @width = 300 

-- Construct new element with attributes 
SET @xml = @xml.query ('<ATTR ID="attr1" CAPTION="{sql:variable("@caption")}" SIZE="{sql:variable("@size")}" WIDTH="{sql:variable("@width")}"></ATTR> ') 

-- Insert it back in 
UPDATE t 
SET yourXML.modify('insert sql:variable("@xml") into (ENTITY[@NAME="entity1"])[1] ') 
FROM @t t 

SELECT 'after' s, * FROM @t 

-- Reconstruct the inner xml END 
------------------------------------------------------------------------------------------------ 



------------------------------------------------------------------------------------------------ 
-- Create mapping table and loop START 
------------------------------------------------------------------------------------------------ 

DECLARE @i INT = 0 
DECLARE @map TABLE (attributeName VARCHAR(50) PRIMARY KEY, newValue VARCHAR(50) NOT NULL) 

INSERT INTO @map (attributeName, newValue) VALUES ('CAPTION', 'New Attribute Caption 3') 
INSERT INTO @map (attributeName, newValue) VALUES ('SIZE', 123) 
INSERT INTO @map (attributeName, newValue) VALUES ('WIDTH', 456) 

SELECT 'before 2' s, * FROM @t 

WHILE 1=1 
BEGIN 

    SET @i += 1 

    -- Update the XML based on the mapping table 
    UPDATE @t 
    SET yourXML.modify('replace value of (/ENTITY/ATTR/@*[local-name()= sql:column("attributeName")])[1] with sql:column("newValue")') 
    FROM @t 
     CROSS JOIN @map m 
    WHERE yourXML.exist('(/ENTITY/ATTR/@*[local-name()= sql:column("attributeName")][. != sql:column("newValue")])') = 1 

    IF @@rowcount = 0 BREAK 

    -- Guard against infinite loop 
    IF @i > 99 BEGIN RAISERROR('Too many loops! %i', 16, 1, @i) BREAK END 

END 

SELECT @i loops 
SELECT 'after' s, * FROM @t 

-- Create mapping table and loop END 
------------------------------------------------------------------------------------------------ 
+0

謝謝,我已經重建了整個XML字符串,一次完成所有更改。 – 2012-08-20 20:16:28