sqlserver xml.modify('replace value of .... with....') 函数改造
2017-12-23 14:03
816 查看
背景: sqlserver 对xml 节点操作会使用xml.modify(‘replace value of …. with….’)函数,但是在使用的过程中发现,该modify函数不支持对空值简写节点的修改. 具体如下
修改
思路: 自定义一个带有三个参数的函数,(@xml,@node,@value), 函数中先插入一个节点,然后把原来的节点删除掉.最终把@xml 返回即可. 因为参数都是未知的,所以必然会涉及到执行动态sql (EXECUTE sp_executesql…..). 理想是美好的,现实是残酷的. 在function 中并不支持动态sql的执行, 含有动态sql的function 虽然编译能通过,但执行会报错(开始处理的时候掉坑里面去了.). 上帝关闭一扇门,就会再打开一扇门. 动态sql可以在procedure 中执行,因此自定义一个存储过程即可
代码如下
测试结果. (注:下面的脚本好有一个自定义函数FN_GETXML() 点击获取该函数(文章开头处)
<person> <name>小明</name> <addr></addr> <org/> </person>
修改
<name>节点和
<addr>节点的值可以成功, 但是修改
<org/>节点的值不能成功. modify不支持对空值简写节点的修改.
思路: 自定义一个带有三个参数的函数,(@xml,@node,@value), 函数中先插入一个节点,然后把原来的节点删除掉.最终把@xml 返回即可. 因为参数都是未知的,所以必然会涉及到执行动态sql (EXECUTE sp_executesql…..). 理想是美好的,现实是残酷的. 在function 中并不支持动态sql的执行, 含有动态sql的function 虽然编译能通过,但执行会报错(开始处理的时候掉坑里面去了.). 上帝关闭一扇门,就会再打开一扇门. 动态sql可以在procedure 中执行,因此自定义一个存储过程即可
代码如下
IF EXISTS (SELECT 1 FROM sysobjects t WHERE t.name = 'proc_replace_node_value') BEGIN DROP PROCEDURE proc_replace_node_value; END; SET QUOTED_IDENTIFIER ON SET ANSI_NULLS ON GO CREATE PROCEDURE [dbo].[proc_replace_node_value] @xml XML OUTPUT,--xml 对象 @node NVARCHAR(1000),--节点表达式 @value NVARCHAR(MAX)--value AS BEGIN ---思路:先在原来的节点后面增加带@value节点,然后删除原来的节点 DECLARE @temp NVARCHAR(1000);--临时变量 DECLARE @nodePath NVARCHAR(1000);--节点路径 DECLARE @nodeShort NVARCHAR(100);--节点名称 DECLARE @replaceSql NVARCHAR(MAX);--替换语句 DECLARE @insertSql NVARCHAR(MAX);--插入节点语句 DECLARE @deleteSql NVARCHAR(MAX);--删除语句 --格式如下(*text())[1] IF CHARINDEX('text())[1]',@node)>0 AND CHARINDEX('(',@node)=1 BEGIN --值为NULL,那么就置为'' IF @value IS NULL BEGIN SET @value = ''; END SELECT @nodePath = SUBSTRING(@node,2,CHARINDEX('text()',@node)-3); --需要操作的节点必须存在,否则不处理 IF @xml.exist('sql:variable("@nodePath")')=1 BEGIN IF LEN(@value)=0 BEGIN --如果value 为空, 直接使用replace. 如果原来的值为空,replace什么也没操作,如果原来有值,就刷成了空 SET @replaceSql = 'SET @xml.modify(''replace value of '+@node +' with "'+@value+'"'''+');'; EXECUTE sp_executesql @replaceSql,N'@xml xml OUTPUT',@xml OUTPUT; END ELSE BEGIN --找到节点名称 SELECT @nodeShort = STUFF(@nodePath,1,LEN(@nodePath)-CHARINDEX('/',REVERSE(@nodePath))+1,''); --拼装路径 SET @nodePath = '('+@nodePath+')[1]'; --如果value中含有单引号必须处理,否则凭借字符串会报错. SET @value = REPLACE(@value,'''',''''''); SET @temp = '<'+@nodeShort+'>'+@value + '</'+@nodeShort+'>'; --在原有节点后面加一个节点 SET @insertSql= 'SET @xml.modify(''insert '+@temp + ' after '+@nodePath +''')'; EXECUTE sp_executesql @insertSql,N'@xml xml OUTPUT',@xml OUTPUT; --删除原有节点 SET @deleteSql = 'SET @xml.modify(''delete '+@nodePath+''')'; EXECUTE sp_executesql @deleteSql,N'@xml xml OUTPUT',@xml OUTPUT; END END; END; END; GO
测试结果. (注:下面的脚本好有一个自定义函数FN_GETXML() 点击获取该函数(文章开头处)
DECLARE @xml XML; SET @xml = dbo.FN_GETXML(); SELECT @xml.query('data/budget_list[1]/PrpManpowers/PrpManpower[1]/ename');--原始值为aaa EXECUTE proc_replace_node_value @xml OUTPUT,'(data/budget_list[1]/PrpManpowers/PrpManpower[1]/ename/text())[1]','88''8'; SELECT @xml.query('data/budget_list[1]/PrpManpowers/PrpManpower[1]/ename');--第一次把aaa 刷成了88'8 EXECUTE proc_replace_node_value @xml OUTPUT,'(data/budget_list[1]/PrpManpowers/PrpManpower[1]/ename/text())[1]',''; SELECT @xml.query('data/budget_list[1]/PrpManpowers/PrpManpower[1]/ename');--第二次把88'8 刷成了空 EXECUTE proc_replace_node_value @xml OUTPUT,'(data/budget_list[1]/PrpManpowers/PrpManpower[1]/ename/text())[1]','666'; SELECT @xml.query('data/budget_list[1]/PrpManpowers/PrpManpower[1]/ename');--第三次把空 刷成了666
相关文章推荐
- Build Data-Driven Web Services with Updated XML Support for SQL Server 2000
- Create XML Files Out Of SQL Server With SSIS And FOR XML Syntax
- Work with XML Data Type in SQL Server 2005 from ADO.NET 2.0
- [优秀英文技术文章转载]Passing lists to SQL Server 2005 with XML Parameters
- [Microsoft][ODBC SQL Server Driver][SQl Server]参数数据类型 text 对于 replace 函数的参数 1 无效。
- Generate XML with data from SQL Server
- Passing lists to SQL Server 2005 with XML Parameters - Jon Galloway
- [Microsoft][ODBC SQL Server Driver][SQl Server]参数数据类型 text 对于 replace 函数的参数 1 无效。
- SqlServer OpenXML函数忽略表中自增列
- Oracle支持的字符函数和它们的Microsoft SQL Server等价函数
- Dynamic XML from SQL Server
- 灵活运用 SQL SERVER FOR XML PATH
- Microsoft SQL Server 2012 Enterprise Edition with Service Pack 1中文版
- SQL SERVER FOR XML PATH
- SQL Server FOR XML PATH 语句的应用
- Logging with SQL Server
- Replace Matches with Replacements Generated in Code (用函数作为替换体来替换匹配)
- SQL Server ISNULL函数和Coalesce函数替换空值的区别
- SqlServer Dev(1) - 存储过程和自定义函数的区别
- Cannot connect to WMI provider.You do not have permission or the server is unreachable.Note that you can only manager SQL Server 2005 and later version with SQL Server Configuration Manager.Invalid namespace [0x8004100e]