разбор строки на подстроки фиксированной ширины

Денис Ильин
Дата: 20.01.2009 13:45:41
на вход хранимой процедуры приходит строка, состоящая исключительно из цифр
каждая цифра в записи имеет строго фиксированную, известную заранее ширину
хочется "затолкать" цифры в табличку. при чём в идеале хочется "чистое sql" решение, но сгодится и "mssql specific" версия.
вот как это сделано сейчас:

set nocount on;

declare @param nvarchar(max)
declare @itemLen int
declare @len int
declare @i int

set @itemLen = 3;
set @param = '1   2   4   6   8   1  ';
set @len = len( @param ) / @itemLen;
set @i = 0;

declare @tmpTab table( id int not null identity(0,1), data int not null );

while( @i <= @len ) begin --нехороший цикл
	insert into @tmpTab
	( data )
	values
	( 0 )
	set @i = @i + 1;
end

update @tmpTab
set data = cast( substring( @param, id * @itemLen, @itemLen ) as int )

select * from @tmpTab

решение достаточно быстро работает, но ещё есть куда расти. есть "нехороший" цикл while.
хочется избавиться от него.
возможнО, это можно сделать как то сразу вставив в таблицу @tmpTable количество записей равное @len (чего вставлять не принципиально).

insert into @tmpTab
( data )
select top(@len) data from junkTable.

однако хрень - если в junkTable меньше @len записей, то количество записей будет меньше.
можно ли как то одной командой (не в цикле) вставить в таблицу @len записей?
iap
Дата: 20.01.2009 13:55:21
Денис Ильин
Дата: 20.01.2009 14:24:18
приведённую ссылку я уже видел, и решение оттуда мне не понравилось наличием таблицы Numbers.
tpg
Дата: 20.01.2009 14:26:32
Денис Ильин
приведённую ссылку я уже видел, и решение оттуда мне не понравилось наличием таблицы Numbers.
Нормальное решение.
Glory
Дата: 20.01.2009 14:52:01
Денис Ильин
приведённую ссылку я уже видел, и решение оттуда мне не понравилось наличием таблицы Numbers.

И что мешает использовать виртуальную, а не реальную таблицу Numbers ?
Денис Ильин
Дата: 20.01.2009 15:10:54
в смысле?
Glory
Дата: 20.01.2009 15:12:24
Денис Ильин
в смысле?

Вы не знаете, что такое виртуальная таблица ?
Это таблица, которая не существует как объект базы и доступна только на время выполнения запроса
alexeyvg
Дата: 20.01.2009 15:13:50
Денис Ильин
решение достаточно быстро работает, но ещё есть куда расти. есть "нехороший" цикл while.
хочется избавиться от него.
Лучьше и от апдэйта тоже избавиться:

set nocount on;

declare @param nvarchar(max)
declare @itemLen int
declare @len int
declare @i int

set @itemLen = 4;
set @param = '1   2   4   6   8   1   ';
set @len = len( @param ) / @itemLen;

declare @tmpTab table( id int not null identity(0,1), data int not null );

insert into @tmpTab( data )
select top(@len+1) cast( substring( @param, ((ROW_NUMBER() over(order by id))-1) * @itemLen, @itemLen ) as int )
from sysobjects
order by id

select * from @tmpTab

Денис Ильин
однако хрень - если в junkTable меньше @len записей, то количество записей будет меньше.
Так возьмите большую таблицу, есть у вас лог какой-нибуть большой? Или кросс-джойны сделайте.
iap
Дата: 20.01.2009 15:14:50
Денис Ильин
в смысле?
Рекурсивное CTE, UNION, ROW_NUMBER() по любой большой таблице, master.dbo.spt_values, CROSS JOIN (если таблицы не хватает), ...
Денис Ильин
Дата: 20.01.2009 15:19:19
alexeyvg
Так возьмите большую таблицу, есть у вас лог какой-нибуть большой

как то... странно это выглядит

alexeyvg
from sysobjects

а если длина строки будет очень большой? гарантировать нельзя. уже сейчас приходят куски с полумилионом циферек.