sql - Parsing range values to comma separated array of values in insert trigger -
i need parsing values in before insert trigger on sql2008 server.
i have table contains text field (lets call source). field value may
10-15,20-22,25-26,
and want comma separated values in field (lets target):
10,11,12,13,14,15,20,21,22,25,26,
can done in before insert trigger or need external app of sort?
thank you.
first need create table valued function takes start , end value generate sequence.this done using recursive cte
create function fngetrange(@startvalue int,@endvalue int) returns @rtntable table ( generatedval varchar(max) ) begin ;with cte(startvalue,rangeval,generatedval) ( select @startvalue,@endvalue,@startvalue generatedval union select startvalue, rangeval, generatedval+1 cte r rangeval > generatedval ) insert @rtntable select generatedval cte return end you need split single column rows can range , pass function
;with cte(range) ( select right(left(t.rangeval,number-1), charindex(',',reverse(left(','+t.rangeval,number-1)))) range master..spt_values, yourtable t type = 'p' , number between 1 , len(t.rangeval)+1 , (substring(t.rangeval,number,1) = ',' or substring(t.rangeval,number,1) = '') ) the above solution posted here uses master..spt_values generate sequence
the cte return result
range 10-15 20-22 25-26 now need split range startvalue , endvalue
rangecte (startvalue,endvalue) ( select parsename(replace(range,'-','.'),2) startvalue, parsename(replace(range,'-','.'),1) endvalue cte ) the above rangecte return data like
startvalue endvalue 10 15 20 22 25 26 once these values need pass function fngetrange using cross apply
rowvalue (rangesep) ( select val.generatedval rangesep rangecte r cross apply dbo.fngetrange(r.startvalue,r.endvalue) val ) this generate sequence in multiple rows .to convert single row use xml path
select stuff( (select ',' + rangesep rowvalue xml path(''),type).value('.','varchar(max)'),1,1,'') now combining cte's final query
;with cte(range) ( select right(left(t.rangeval,number-1), charindex(',',reverse(left(','+t.rangeval,number-1)))) range master..spt_values, yourtable t type = 'p' , number between 1 , len(t.rangeval)+1 , (substring(t.rangeval,number,1) = ',' or substring(t.rangeval,number,1) = '') ),rangecte (startvalue,endvalue) ( select parsename(replace(range,'-','.'),2) startvalue, parsename(replace(range,'-','.'),1) endvalue cte ),rowvalue (rangesep) ( select val.generatedval rangesep rangecte r cross apply dbo.fngetrange(r.startvalue,r.endvalue) val ) select stuff( (select ',' + rangesep rowvalue xml path(''),type).value('.','varchar(max)'),1,1,'') the result
10,11,12,13,14,15,20,21,22,25,26 as others have suggested ,you should change table design .instead of storing string create columns store range of type int
updated
just on same page . create insert trigger on source table contains values 10-15,20-22,25-26.you need convert these values sequence , insert target table.if case can use below code.
basically trigger created derived table inserts data inserted logical tables in trigger.then using above nested cte's ,you insert sequence in target table
create trigger tri_inserts on after insert set nocount on declare @rangetable table (rangeval varchar(max)) insert @rangetable select rangecolumn inserted ;with cte(range) ( select right(left(t.rangeval,number-1), charindex(',',reverse(left(','+t.rangeval,number-1)))) range master..spt_values, @rangetable t type = 'p' , number between 1 , len(t.rangeval)+1 , (substring(t.rangeval,number,1) = ',' or substring(t.rangeval,number,1) = '') ),rangecte (startvalue,endvalue) ( select parsename(replace(range,'-','.'),2) startvalue, parsename(replace(range,'-','.'),1) endvalue cte ),rowvalue (rangesep) ( select val.generatedval rangesep rangecte r cross apply dbo.fngetrange(r.startvalue,r.endvalue) val ) insert target(destcolumn) --change target name select stuff( (select ',' + rangesep rowvalue xml path(''),type).value('.','varchar(max)'),1,1,'') go
Comments
Post a Comment