powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / разбить строку text
20 сообщений из 20, страница 1 из 1
разбить строку text
    #32048363
brams
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Уважаемые гуру, подскажите, плз.
Задача - разбить в UDF строку ЛЮБОЙ длинны по разделителям и вернуть результат в виде таблицы.

Я написал UDF, которая принимала строку и прекрасно справлялась до тех пор, пока строка не превышала 8000 символов.

С text трахался, и ни хрена не получилось((

Подсобите, пожалуйста.

Заранее спасибо.
...
Рейтинг: 0 / 0
разбить строку text
    #32048369
Фотография Lexis
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
посмотри две процедурки, может после модификации они тебе помогут?

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
CREATE procedure usp_parser
@in_string	varchar( 4000 ), 
@separator	varchar( 1 ),
@out_string	varchar( 4000 ) output,
@out_part	varchar( 255 ) output

as
declare @start_position	int
declare @position	int
declare @len_string	int

select @start_position= 1 
select @position=charindex(@separator,@in_string)- 1 
if @position> 0 
begin
 select @len_string=len(@in_string)
 select @out_part=substring(@in_string,@start_position,@position)
 select @out_string=substring(@in_string,@position+ 2 ,@len_string)
end
else
begin
 set @out_part=@in_string
 set @out_string=''
end
GO

CREATE procedure usp_calcpart
@in_string	char( 4000 ),
@separator	char( 1 ),
@nmb		int output

as
declare @work_str	char( 4000 )
declare @start_pos	int

set @nmb= 0 
set @work_str=@in_string
while charindex(@separator,@work_str)> 0  and len(@work_str)> 3 
begin
  set @start_pos=charindex(@separator,@work_str)+ 1 
  set @nmb=@nmb+ 1 
  set @work_str=rtrim(substring(@work_str,@start_pos, 4000 ))

end
GO
...
Рейтинг: 0 / 0
разбить строку text
    #32048370
Glory
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Я использую такой метод

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[sp_ArrayString2Table2]') and OBJECTPROPERTY(id, N'IsProcedure') =  1 )
drop procedure [dbo].[sp_ArrayString2Table2]
GO


CREATE PROCEDURE [dbo].[sp_ArrayString2Table2]
	@instr text=NULL, @rowpattern varchar( 100 ) = '//node'
AS

IF @instr IS NULL
	RETURN - 1 

DECLARE @XMLHandler int

EXEC sp_xml_preparedocument @XMLHandler OUTPUT, @instr  
SELECT * FROM OpenXML(@XMLHandler, @rowpattern,  0 ) WITH (value int '@value')
EXEC sp_xml_removedocument @XMLHandler


go

create table #t(value int)
insert #t exec [dbo].[sp_ArrayString2Table2] '<root><node value="1"></node><node value="2"></node><node value="3"></node><node value="4"></node></root>'
select * from #t
drop table #t
go
...
Рейтинг: 0 / 0
разбить строку text
    #32048385
brams
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
2Glory.
Трабла в том, что я не могу использовать sp_xml_preparedocument внутри фции...
...
Рейтинг: 0 / 0
разбить строку text
    #32048394
Glory
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Да, не можете.
Придется выбирать UDF vs PROCEDURE.
...
Рейтинг: 0 / 0
разбить строку text
    #32048398
brams
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
2Lexis - типа такого у меня и есть, только в UDF. и проблему длинных строк это, к сожалению, не решает.
...
Рейтинг: 0 / 0
разбить строку text
    #32048414
GreenSunrise
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
1. Если элементы строк могут превышать 8000 байт, т.е. выходная таблица будет содержать поле типа text (ntext) для них, то UDF написать нельзя, потому что
- если попытаться использовать substring, то получим облом - параметр length не может превышать 8000
- если формировать элементы посимвольно, то нужно использовать textptr, а это в UDF не получится

2. Если вся строка может быть больше 8000, а элементы - нет, то, возможно , и получится.

3. Почему бы не попытаться прогнать через bcp, указав свой разделитель как разделитель строк , а не столбцов ? Как раз в таблицу все и сольется.

Если второй вариант вас устраивает, то можно продолжить :-)
Хотя третий мне кажется более привлекательным.
...
Рейтинг: 0 / 0
разбить строку text
    #32048416
brams
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
2GreenSunrise:
Да, второй вариант меня устраивает - жлементы явно не будут больше 8000.

А что насчет bcp? я с ним никогда не работал((

у меня задача - из ASP передаю в SQL ДЛИННУЮ строку идентификаторов.
...
Рейтинг: 0 / 0
разбить строку text
    #32048420
brams
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
у меня уже написана куча кода, типа такого:

Код: plaintext
1.
update tabOrders set status=@status where id in (select item from dbo.fSplit(@orderList, ', '))


а вот fSplit:

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
CREATE FUNCTION fSplit(@list varchar( 8000 ), @delimer char( 1 ))
RETURNS @res table  (item varchar( 500 ))
AS  
BEGIN 
declare @i int
set @i=charindex(@delimer, @list,   0 )
while @i> 0 
begin
	insert into @res values (left(@list, @i- 1 ))
	set @list=substring(@list, @i+len(@delimer)+ 1 , len(@list)-@i)
	set @i=charindex(@delimer, @list,   0 )
end
insert into @res values (@list)
return
END


Во время испытания на реальных данных выяснилось, что 8000 не хватает((. Код менять в куче мест и снова отлаживать - не прет совершенно, хотелось бы поменять UDF.

Прокатит?
...
Рейтинг: 0 / 0
разбить строку text
    #32048421
GreenSunrise
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Не, bcp в функции все равно не прокатит... Пардон, переклинило на sp обычные. Просто показалось, что это самый простой и универсальный вариант.

Ладно, займемся вторым :-)
...
Рейтинг: 0 / 0
разбить строку text
    #32048435
GreenSunrise
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Например, так:

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
create function fSplit (@list text, @delimiter char( 1 ))
returns @res table (item varchar( 500 ))
as
begin
	declare @start int
	declare @end int
	set @start =  1 
	set @end = charindex(@delimiter, @list, @start)

	while @end >  0 
	begin
		insert into @res values (substring(@list, @start, @end - @start))
		set @start = @end +  1 
		set @end = charindex(@delimiter, @list, @start)
	end

	insert into @res values (substring(@list, @start, datalength(@list) - @start +  1 ))

	return
end

Или так:

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
create function fSplit (@list text, @delimiter char( 1 ))
returns @res table (item varchar( 500 ))
as
begin
	declare @i int
	declare @item varchar( 500 )

	set @i =  1 
	set @item = ''

	while @i <= datalength(@list)
	begin
		if substring(@list, @i,  1 ) <> @delimiter
			set @item = @item + substring(@list, @i,  1 )
		else
		begin
			insert into @res values (@item)
			set @item = ''
		end

		set @i = @i +  1 
	end

	return
end

Сами посмотрите, что производительнее.

Кстати, а вы уверены, что @delimiter char(1) - это хорошо? В вашем примере делимитер явно двухсимвольный :-)

И еще - ваш пример неправильно сработал на тесте select item from dbo.fSplit('012.456567.df.rt', '.'). Лень разбираться, что там неправильно.
...
Рейтинг: 0 / 0
разбить строку text
    #32048436
brams
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
2GreenSunrise - СПАСИБО ОФИГЕННОЕ!

Сейчас попробую!

delimer char(1) - это, конечно, да.)

а с ошибкой гляну.

Спасибо еще раз.
...
Рейтинг: 0 / 0
разбить строку text
    #32048446
GreenSunrise
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Если делимитер не односимвольный, то функции надо менять, чтобы это учитывать, в данном виде работать не будут. Думаю, и без меня справитесь ;-)
...
Рейтинг: 0 / 0
разбить строку text
    #32048450
brams
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
2GreenSunrise - с меня пиво!

куда проставлять?
...
Рейтинг: 0 / 0
разбить строку text
    #32048452
GreenSunrise
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
То есть помогло?
Я пиво не пью. Обойдемся "спасибом" :-))
...
Рейтинг: 0 / 0
разбить строку text
    #32048463
Slava
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Если позволите могу похвастаться чуть более быстрым вариантом
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
CREATE FUNCTION F_CODES_IN_TABLE 
	(@strCodes text)
RETURNS @tmp TABLE 
	(code varchar( 20 ))
AS
BEGIN
	declare @i int set @i =  1 
	declare @code varchar( 20 ) set @code = ''
	declare @len int set @len = datalength(@strCodes) +  1 
	declare @char char( 1 )
	while @i < @len begin
		set @char = substring(@strCodes, @i,  1 )
		if @char <> ';'
			set @code = @code + @char
		else begin
			insert into @tmp values(@code)
			set @code = ''
		end
		set @i = @i +  1 
	end
	insert into @tmp values(@code)
	delete from @tmp where code = ''
	RETURN
END

"быстрость" заметна только когда строка кодов больше 8000. На 16000 выигрышь в пару секунд
...
Рейтинг: 0 / 0
разбить строку text
    #32048484
Фотография SergSuper
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
2 GreenSunrise

если попытаться использовать substring, то получим облом - параметр length не может превышать 8000

ой как я Вас еще обрадую: начиная с 7-й версии - может

2 brams
а ведь не обязательно передавать сам text, можно же передавать ключ записи, где есть это поле
...
Рейтинг: 0 / 0
разбить строку text
    #32048488
brams
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
2Slava - спасибо, будем ускоряться!

2SergSuper - дело в том, что text берется НЕ из таблицы, а пихать его туда...
...
Рейтинг: 0 / 0
разбить строку text
    #32048491
GreenSunrise
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
2SergSuper: really?

Такой примерчик:

create table t1 (col1 text)
insert into t1 values ('тут очень длинная строка')

Для проверки:

select datalength(col1) from t1

-----------
10000

select substring(col1, 1, 9000) from t1

возвращает ошибку: Expression result length exceeds the maximum. 8000 max, 9000 found.

MSSQL 2000

И?..
...
Рейтинг: 0 / 0
разбить строку text
    #32048500
Фотография SergSuper
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
2 GreenSunrise
пардон, да конечно длинна должна быть меньше, а я имел в виду что кусок текста может быть где угодно, т.е. start.
...
Рейтинг: 0 / 0
20 сообщений из 20, страница 1 из 1
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / разбить строку text
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]