你確實有幾個選擇,但可能不會比你的三個更新更好。選項是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
------------------------------------------------------------------------------------------------
沒有,據我所知,有沒有辦法多個更新合併到一個XML列到一個單獨的語句。你有什麼作品 - 離開它。 – 2012-08-09 19:37:51
可能重複[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