我需要使用TSQL变量的内容更新XML元素中的值。增加的复杂性是可以有多个具有相同名称的元素,并且所有元素都需要更新。这是一个例子。请注意,客户1000000有两个customer_firstname元素。
CREATE TABLE Customer_Test
(
[customer_data] [xml] NULL
)
-- populate statements
insert into Customer_Test (customer_data) values ('<Customer Note="two customer_firstnames"><customer_id>1000000</customer_id><customer_firstname>Mary</customer_firstname><customer_firstname>Jane</customer_firstname><customer_lastname>Smith</customer_lastname></Customer>');
insert into Customer_Test (customer_data) values ('<Customer Note="normal, no problem"><customer_id>1000001</customer_id><customer_firstname>Joe</customer_firstname><customer_lastname>Bloggs</customer_lastname></Customer>');
以下代码在xml结构上运行得很好,就像在customer_ID ='1000001'记录中一样,但只有第一个customer_firstname元素在customer_ID ='1000000'
等情况下才会更新DECLARE @newName varchar(10) = 'xxx'
DECLARE @IDValue varchar(10) = '1000000'
UPDATE [Customer_Test]
SET customer_data.modify('replace value of (Customer/customer_firstname/text())[1] with sql:variable("@newName")')
WHERE customer_data.value('(/Customer/customer_id)[1]','varchar(50)') = @IDValue
我真的坚持这个 - 我需要将customer_firstname元素的所有值设置为相同的值(如果它们存在)。我怀疑是否需要CROSS APPLY,但我编写代码的所有尝试都无法编译。
我非常重视可能提供的任何建议。提前谢谢。
答案 0 :(得分:2)
使用一个更新语句无法更新XML中的多个值。
您可以在while循环中执行此操作,该循环会迭代您在一个XML中拥有的名字数。
DECLARE @newName varchar(10) = 'xxx'
DECLARE @IDValue varchar(10) = '1000000'
DECLARE @FirstNameCount INT
-- Get the max number of first names in one XML
SELECT @FirstNameCount = max(customer_data.value('count(Customer/customer_firstname)', 'int'))
FROM Customer_Test
WHERE customer_data.value('(/Customer/customer_id)[1]','varchar(50)') = @IDValue
-- Loop over @FirstNameCoount
WHILE @FirstNameCount > 0
BEGIN
UPDATE [Customer_Test]
SET customer_data.modify('replace value of (Customer/customer_firstname[sql:variable("@FirstNameCount")]/text())[1] with sql:variable("@newName")')
WHERE customer_data.value('(/Customer/customer_id)[1]','varchar(50)') = @IDValue
SET @FirstNameCount = @FirstNameCount - 1
END
答案 1 :(得分:0)
此时是否值得对重复数据删除进行重复数据删除?如果要将所有值设置为相同的值,那么存储第二个名称实际上没有意义。您可以根据其位置删除第二个customer_firstname元素,例如
SELECT 'before' s, DATALENGTH( customer_data ) dl, [customer_data] FROM Customer_Test
UPDATE [Customer_Test]
SET customer_data.modify('delete Customer/customer_firstname[position() > 1]')
SELECT 'after 1' s, DATALENGTH( customer_data ) dl, [customer_data] FROM Customer_Test
DECLARE @newName varchar(10) = 'xxx'
DECLARE @IDValue varchar(10) = '1000000'
UPDATE [Customer_Test]
SET customer_data.modify('replace value of (Customer/customer_firstname/text())[1] with sql:variable("@newName")')
WHERE customer_data.value('(/Customer/customer_id)[1]','varchar(50)') = @IDValue
SELECT 'after 2' s, DATALENGTH( customer_data ) dl, [customer_data] FROM Customer_Test