How to create a schema-bound function that counts nodes in an xml and then be able to persist this result in a column
I have an xml column and I want to persist a node count in it in an adjacent column.
For example, in an xml given below, I have 3 nodes a
and so I want to output it.
The problem that I have, however, is that I can't manage to create a generic schema-bound function that would take @xml and @nodeName so as to return the count of a specified node.
create function dbo.fnXmlCount_a (@xml xml)
returns int with schemabinding
as begin
return (@xml.value('count(//a)', 'int'))
end
declare @xml xml;
set @xml = '
<r>
<a></a>
<b></b>
<a></a>
<c>
<a></a>
</c>
</r>'
select dbo.fnXmlCount_a(@xml) aCount
Result of the last operation is:
aCount
3
And then I create a column on that table that has this xml field like so:
alter table [XmlTable] add column [aCount] as (dbo.fnXmlCount_a([xml])) persisted
But what I really would like to do is this:
alter table [XmlTable] add column [aCount] as (dbo.fnXmlNodeCou开发者_运维百科nt([xml], 'a')) persisted
Thanks!
Update:
We all know that //
is really slow, so it would be great if you could figure out how to pass this path to search in in another variable; by default, this searching path would be //
.
Here you go:
create function dbo.fnXmlCount (@xml xml, @name nvarchar(max))
returns int with schemabinding
as begin
declare @count int
select @count = count(*)
from @xml.nodes('//*') as t(c)
where t.c.value('local-name(.)', 'nvarchar(max)') = @name
return @count
end
I have come up with a little better solution but the approach is similar to that of Daniel Renshaw.
create function [dbo].[fnXmlCount] (@xml xml, @nodeName nvarchar(max))
returns int with schemabinding
as begin
return @xml.value('count(//*[local-name() = sql:variable("@nodeName")])', 'int')
end
However, there's still no solution as to how to pass the path to nodes being counted.
And it takes about 20 seconds to count nodes on my xml table.
精彩评论