我试图修改XML值但继续收到消息
替换的目标必须至多是一个节点,找到属性(prefType,xdt:untypedAtomic)
首先是我的XML
<preferences>
<categories>
<category id="1" prefType="2">
<subcat id="1" prefType="2" />
<subcat id="2" prefType="2" />
<subcat id="3" prefType="2" />
<subcat id="77" prefType="2" />
</category>
<category id="2" prefType="2">
<subcat id="9" prefType="2" />
<subcat id="10" prefType="2" />
<subcat id="11" prefType="2" />
<subcat id="12" prefType="2" />
<subcat id="13" prefType="2" />
<subcat id="14" prefType="2" />
<subcat id="17" prefType="2" />
<subcat id="78" prefType="2" />
<subcat id="101" prefType="2" />
</category>
<category id="3" prefType="2">
<subcat id="18" prefType="2" />
<subcat id="19" prefType="2" />
<subcat id="20" prefType="2" />
</category>
</categories>
</preferences>
我的代码
declare @XMLinput as XML;
declare @custXML as XML;
declare @subcatid as nvarchar(3);
declare @interest as nvarchar(8);
declare @newValue as varchar(1);
declare @cnt as int;
set @XMLinput = '<preferences><categoryId>73</categoryId><interestLevel>POSITIVE</interestLevel></preferences>';
-- get the subcatid and interest level
SET @subcatid = @XMLinput.value('(//preferences/categoryId)[1]','nvarchar(3)');
SET @interest = @XMLinput.value('(//preferences/interestLevel)[1]','nvarchar(20)');
SET @newValue =
CASE @interest
WHEN 'POSITIVE' THEN '1'
WHEN 'NEGATIVE' THEN '3'
ELSE '2'
END;
set @custXML = (select Preferences from Customer_Preferences where custID=11584);
select @custXML.exist('//preferences/categories/category/subcat[@id=sql:variable("@subcatid")]');
if (@@ROWCOUNT > 0)
BEGIN TRY
BEGIN TRAN;
set @cnt = CAST(CAST(@custXML.query('count(//preferences/categories/category/subcat[@id=(sql:variable("@subcatid"))])') AS VARCHAR) AS INT);
-- replace the value
UPDATE Customer_Preferences
SET preferences.modify('
replace value of
(//*/subcat[@id=sql:variable("@subcatid")]/@prefType[1])
with sql:variable("@newValue")
')
where CustID = 11584;
COMMIT TRAN;
END TRY
BEGIN CATCH
select XACT_STATE() as 'XACT_STATE', @@TRANCOUNT as '@@TRANCOUNT';
if @@TRANCOUNT > 0 ROLLBACK TRANSACTION;
END CATCH
select preferences from Customer_Preferences where custid=11584
SELECT XACT_STATE() as 'XACT_STATE', @@TRANCOUNT AS '@@TRANCOUNT'
我尝试删除sql变量并用固定值替换它们但仍然遇到同样的问题。我还尝试删除所有XML子类,除了发生同一个错误。
经过3个小时的工作并且没有任何地方,我非常感谢你的帮助。
答案 0 :(得分:2)
正如进一步参考(虽然你已经解决了你自己的问题)对于有类似问题的其他人:这是实际出错的地方:错误信息已经表明替换目标最多只能有一个值(意味着你可以一次只能替换一个值。)
但是,(//*/subcat[@id=sql:variable("@subcatid")]/@prefType[1])
会产生一系列结果。字面意思是指每个subcat
元素和选择名称为prefType
的第一个属性。这实际上没有多大意义,因为XML元素不能具有多个具有相同名称的属性,因此在没有[1]
谓词的情况下查询将是相同的。
您可能想要写的是:给我每个prefType
元素的每个subcat
属性,并仅返回整个结果集中的第一个。这正是您的工作查询正在执行的操作:(//*/subcat[@id=sql:variable("@subcatid")]/@prefType)[1]