动态修改XML标签值失败:存储过程执行正常但未生效求助
问题分析与解决
你的代码无法修改XML值,主要有三个关键问题:
1. XPath节点定位错误
你在modify方法里的XPath路径写错了:
/ArrayOfNoteParameterDC[ParameterEnum = ''AccountNumber'']/Value/text()
正确的路径必须定位到NoteParameterDC节点下的ParameterEnum——因为ParameterEnum是NoteParameterDC的子节点,不是ArrayOfNoteParameterDC的直接子节点。修正后路径:
/ArrayOfNoteParameterDC/NoteParameterDC[ParameterEnum = ''AccountNumber'']/Value/text()
2. SQL变量引用方式错误
你当前是把字符串"@vcCustAccountID"直接写入XML,而非引用变量的实际值。在XML DML中引用SQL变量,必须用sql:variable("@变量名")语法,不能直接把变量名当字符串传递。
3. 低效的WHILE循环(可选优化)
你用临时表+循环逐个更新的方式效率很低,完全可以改成批量更新,无需循环。
修正后的代码(保留原逻辑版本)
先把循环内的UPDATE语句修正:
DROP TABLE IF EXISTS #IDsToUpdate SELECT biCustNoteID, biAccountID INTO #IDsToUpdate FROM tbCustNote WHERE vcParams.value('(/ArrayOfNoteParameterDC/NoteParameterDC[ParameterEnum = ''AccountNumber'']/Value/text())[1]', 'varchar(max)') = vcParams.value('(/ArrayOfNoteParameterDC/NoteParameterDC[ParameterEnum = ''SourceAccountNumber'']/Value/text())[1]', 'varchar(max)') WHILE EXISTS (SELECT * FROM #IDsToUpdate) BEGIN DECLARE @Id bigint SET @Id = (SELECT TOP 1 biCustNoteID FROM #IDsToUpdate); DECLARE @biCustAccountID bigint SET @biCustAccountID = (SELECT TOP 1 biAccountID FROM #IDsToUpdate WHERE biCustNoteID = @Id); DECLARE @vcCustAccountID varchar(max) -- 注意:vcAccountID如果是字符串类型,要对应varchar,避免类型转换问题 SET @vcCustAccountID = (SELECT TOP 1 vcAccountID FROM tbcustaccount WHERE biaccountid = @biCustAccountID); WITH XMLNAMESPACES('http://www.w3.org/2001/XMLSchema-instance' as xsi, 'http://www.w3.org/2001/XMLSchema' as xsd) UPDATE tbCustNote SET vcParams.modify('replace value of (/ArrayOfNoteParameterDC/NoteParameterDC[ParameterEnum = ''AccountNumber'']/Value/text())[1] with sql:variable("@vcCustAccountID")') WHERE biCustNoteID = @Id DELETE #IDsToUpdate WHERE biCustNoteID = @Id END
优化后的批量更新版本(推荐)
直接关联表批量更新,去掉循环和临时表,效率更高:
WITH XMLNAMESPACES('http://www.w3.org/2001/XMLSchema-instance' as xsi, 'http://www.w3.org/2001/XMLSchema' as xsd) UPDATE cn SET cn.vcParams.modify('replace value of (/ArrayOfNoteParameterDC/NoteParameterDC[ParameterEnum = ''AccountNumber'']/Value/text())[1] with sql:column("ca.vcAccountID")') FROM tbCustNote cn JOIN tbcustaccount ca ON cn.biAccountID = ca.biaccountid WHERE cn.vcParams.value('(/ArrayOfNoteParameterDC/NoteParameterDC[ParameterEnum = ''AccountNumber'']/Value/text())[1]', 'varchar(max)') = cn.vcParams.value('(/ArrayOfNoteParameterDC/NoteParameterDC[ParameterEnum = ''SourceAccountNumber'']/Value/text())[1]', 'varchar(max)')
这里用sql:column("表名.列名")直接引用关联表的列值,无需额外定义变量,写法更简洁。
内容的提问来源于stack exchange,提问作者bruno valverde
相关产品推荐
相关产品推荐

