Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Microsoft SQL Server Новый топик    Ответить
 Конкатенация строк в nvarchar(max)  [new]
ResearchStudio
Member [заблокирован]

Откуда: страна ленивых программистов
Сообщений: 2506
Есть таблица, порядка 140 тысяч записей
вида


create table Table1
(
   Result nvarchar(max)
)


Нужно вытянуть все значения из этой таблицы в одну длинную строку nvarchar(max).
Раньше делалось это курсором по этой таблице и по кусочку строчки конкатентились.
Но это дело жутко тормозит. Подозреваю при каждой конкатенации вызывает постоянное перераспределение памяти. В пару раз ускорил это дело используя промежуточный буфер.
вида

        declare @Text nvarchar(4000), @Buffer nvarchar(4000), @WholeText nvarchar(max)

	set @WholeText = ''

	declare curs cursor local for select Result from #Result
	open curs
	fetch next from curs into @Text
	while @@fetch_status = 0 begin

		if (len(@Buffer) > 0) 
		begin
			set @Buffer = @Buffer + char(13) + char(10) + @Text
		end
		else
		begin 
			set @Buffer = @Text
		end

		if(len(@Buffer) > 2000)
		begin
			set @WholeText = @WholeText + @Buffer
			set @Buffer = ''
		end

		fetch next from curs into @Text
	end
	close curs
	deallocate curs
	select Result from #Result
	set @Output = @WholeText
	drop table #Result
end


Но скорость работы всеравно недопустимая. Кто-то сталкивался, что тут можно еще сделать ?
Сейчас копаю в сторону бинарного схлопывания таблицы. Тоесть сначала в таблице конкатентим одним апдейтом четные и нечетные записи, потом нечетные удаляем, потом снова четные и нечетные и так далее пока не окажется в конце одна запись.
30 сен 09, 13:32    [7724510]     Ответить | Цитировать Сообщить модератору
 Re: Конкатенация строк в nvarchar(max)  [new]
ResearchStudio
Member [заблокирован]

Откуда: страна ленивых программистов
Сообщений: 2506
да, MS SQL 2005
30 сен 09, 13:33    [7724516]     Ответить | Цитировать Сообщить модератору
 Re: Конкатенация строк в nvarchar(max)  [new]
Паганель
Member

Откуда: Винница
Сообщений: 22552
ResearchStudio
Есть таблица, порядка 140 тысяч записей
ResearchStudio
Нужно вытянуть все значения из этой таблицы в одну длинную строку nvarchar(max).
Хотел бы я посмотреть, как пользователь полученный отчет на печать отправит
30 сен 09, 13:39    [7724563]     Ответить | Цитировать Сообщить модератору
 Re: Конкатенация строк в nvarchar(max)  [new]
PaulYoung
Member

Откуда: Москва
Сообщений: 2549
ResearchStudio,

Вам не это надо?
30 сен 09, 13:40    [7724578]     Ответить | Цитировать Сообщить модератору
 Re: Конкатенация строк в nvarchar(max)  [new]
Влом регистрироваться
Guest
ResearchStudio,

FAQ->Сложение символьных полей в запросе
30 сен 09, 13:42    [7724591]     Ответить | Цитировать Сообщить модератору
 Re: Конкатенация строк в nvarchar(max)  [new]
ResearchStudio
Member [заблокирован]

Откуда: страна ленивых программистов
Сообщений: 2506
Нет, не то, это задача перформанца
30 сен 09, 13:48    [7724637]     Ответить | Цитировать Сообщить модератору
 Re: Конкатенация строк в nvarchar(max)  [new]
ResearchStudio
Member [заблокирован]

Откуда: страна ленивых программистов
Сообщений: 2506
Паганель
ResearchStudio
Есть таблица, порядка 140 тысяч записей
ResearchStudio
Нужно вытянуть все значения из этой таблицы в одну длинную строку nvarchar(max).
Хотел бы я посмотреть, как пользователь полученный отчет на печать отправит


1С нек ?
30 сен 09, 13:49    [7724641]     Ответить | Цитировать Сообщить модератору
 Re: Конкатенация строк в nvarchar(max)  [new]
ResearchStudio
Member [заблокирован]

Откуда: страна ленивых программистов
Сообщений: 2506
в принципе проблема отпала, бинарную таблицу реализовал - но медленно работает, не делайте.
Буффер в принципе помог плюс пара мелких оптимизаций по коду.
Весь экспорт на рабочей базе ушел с >1.5 часа до 10 минут.
30 сен 09, 14:10    [7724770]     Ответить | Цитировать Сообщить модератору
 Re: Конкатенация строк в nvarchar(max)  [new]
vino
Member

Откуда:
Сообщений: 1191
ResearchStudio
create table Table1
(
Result nvarchar(max)
)
...
declare @Text nvarchar(4000), @Buffer nvarchar(4000), @WholeText nvarchar(max)
...
declare curs cursor local for select Result from #Result
open curs
fetch next from curs into @Text
...
set @Output = @WholeText

плохое сочетание, особенно - выгрузка безлимитных значений в 4000 символьную переменную.
я так понимаю, что уже опробовано, тогда - сколько времени длится?
select @Output = isnull(@Output + char(13) + char(10) + Result, Result) from Table1 with(nolock)
30 сен 09, 14:18    [7724821]     Ответить | Цитировать Сообщить модератору
 Re: Конкатенация строк в nvarchar(max)  [new]
Влом регистрироваться
Guest
ResearchStudio,

а BCP, FOR XML и т.д. - религия не позволяет пользоваться?
30 сен 09, 14:19    [7724823]     Ответить | Цитировать Сообщить модератору
 Re: Конкатенация строк в nvarchar(max)  [new]
ResearchStudio
Member [заблокирован]

Откуда: страна ленивых программистов
Сообщений: 2506
Влом регистрироваться
ResearchStudio,

а BCP, FOR XML и т.д. - религия не позволяет пользоваться?


да я минут десять назад додумался и сделал

declare @output nvarchar(max)

set @output = 
CAST((SELECT Result
FROM #Result
FOR XML RAW) AS nvarchar(max))

set @output = replace(@output, '<row Result="', '')
set @output = replace(@output, '"/>', '')

print len(@output)
30 сен 09, 14:27    [7724863]     Ответить | Цитировать Сообщить модератору
 Re: Конкатенация строк в nvarchar(max)  [new]
DeColo®es
Member

Откуда: Москва
Сообщений: 5499
Блог
Проще:
select Result
from #Result
for xml path('')
30 сен 09, 15:10    [7725135]     Ответить | Цитировать Сообщить модератору
 Re: Конкатенация строк в nvarchar(max)  [new]
vino
Member

Откуда:
Сообщений: 1191
DeColo®es
Проще:
select Result
from #Result
for xml path('')
я так понимаю, автору нужен в @output список строк без лишних символов, но... это будет быстрее чем конкатенируюшщий запрос?
30 сен 09, 15:20    [7725216]     Ответить | Цитировать Сообщить модератору
 Re: Конкатенация строк в nvarchar(max)  [new]
ResearchStudio
Member [заблокирован]

Откуда: страна ленивых программистов
Сообщений: 2506
vino
DeColo®es
Проще:
select Result
from #Result
for xml path('')
я так понимаю, автору нужен в @output список строк без лишних символов, но... это будет быстрее чем конкатенируюшщий запрос?


да, не намного но быстрее. Правда решение конечно красивее чем через курсор :)

Кто будет использовать не забываем про спец символы еще в хмл

вот что на эксперементальных данных нашлось
SET @Output = replace(@Output, '"', '"')
SET @Output = replace(@Output, '&', '&')
SET @Output = replace(@Output, '<', '<')
SET @Output = replace(@Output, '>', '>')
SET @Output = replace(@Output, '
', CHAR(0x0D))
SET @Output = replace(@Output, '
', CHAR(0x0A))
30 сен 09, 15:37    [7725348]     Ответить | Цитировать Сообщить модератору
 Re: Конкатенация строк в nvarchar(max)  [new]
DeColo®es
Member

Откуда: Москва
Сообщений: 5499
Блог
vino
я так понимаю, автору нужен в @output список строк без лишних символов, но... это будет быстрее чем конкатенируюшщий запрос?
Что есть конкатенирующий запрос? ;)
конструкция select @var = @var + field1 from table1, если речь о ней - недокументирована(и работоспособность ее сильно зависит от фазы луны), в соседней ветке обсуждается.
Так что конкатеация строк varchar(max) в 2005 версии доступна либо через xml, либо курсором, который явно медленнее.
30 сен 09, 15:38    [7725350]     Ответить | Цитировать Сообщить модератору
 Re: Конкатенация строк в nvarchar(max)  [new]
ResearchStudio
Member [заблокирован]

Откуда: страна ленивых программистов
Сообщений: 2506
vino
DeColo®es
Проще:
select Result
from #Result
for xml path('')
я так понимаю, автору нужен в @output список строк без лишних символов, но... это будет быстрее чем конкатенируюшщий запрос?


Работает быстрее. nvarchar(max) относится к так называемым тяжелым типам сиквел сервера
30 сен 09, 15:38    [7725355]     Ответить | Цитировать Сообщить модератору
 Re: Конкатенация строк в nvarchar(max)  [new]
vino
Member

Откуда:
Сообщений: 1191
ResearchStudio
...Кто будет использовать не забываем про спец символы еще в хмл

вот что на эксперементальных данных нашлось
SET @Output = replace(@Output, '"', '"')
SET @Output = replace(@Output, '&', '&')
SET @Output = replace(@Output, '<', '<')
SET @Output = replace(@Output, '>', '>')
SET @Output = replace(@Output, '
', CHAR(0x0D))
SET @Output = replace(@Output, '
', CHAR(0x0A))

не забываем спецификацию xml: набор спецсимволов вполне документирован, например, & это символ & и т.д.
30 сен 09, 15:55    [7725486]     Ответить | Цитировать Сообщить модератору
 Re: Конкатенация строк в nvarchar(max)  [new]
vino
Member

Откуда:
Сообщений: 1191
vino
...например, & это символ & и т.д.
имелся в виду, конечно, &amp;
30 сен 09, 15:59    [7725528]     Ответить | Цитировать Сообщить модератору
 Re: Конкатенация строк в nvarchar(max)  [new]
vino
Member

Откуда:
Сообщений: 1191
в общем, подправим, хотя бы так:
SET @Output = replace(@Output, '&quot;', '"')
SET @Output = replace(@Output, '&amp;', '&')
SET @Output = replace(@Output, '&lt;', '<')
SET @Output = replace(@Output, '&gt;', '>')
SET @Output = replace(@Output, '&apos;', '''')
SET @Output = replace(@Output, '&#13;', CHAR(0x0D))
SET @Output = replace(@Output, '&#10;', CHAR(0x0A))
что лучше выполнять так:
SET @Output = replace(replace(replace(replace(replace(replace(replace(
@Output, '&quot;', '"'), '&amp;', '&'), '&lt;', '<'), '&gt;', '>'),
'&apos;', ''''), '&#13;', CHAR(0x0D)), '&#10;', CHAR(0x0A))
30 сен 09, 16:15    [7725643]     Ответить | Цитировать Сообщить модератору
 Re: Конкатенация строк в nvarchar(max)  [new]
vino
Member

Откуда:
Сообщений: 1191
и еще неточность - амперсанд надо заменять в последнюю очередь:
SET @Output = replace(@Output, '&quot;', '"')
SET @Output = replace(@Output, '&lt;', '<')
SET @Output = replace(@Output, '&gt;', '>')
SET @Output = replace(@Output, '&apos;', '''')
SET @Output = replace(@Output, '&#13;', CHAR(0x0D))
SET @Output = replace(@Output, '&#10;', CHAR(0x0A))
-- здесь в общем случае заменяются любые символы вида &#код;
SET @Output = replace(@Output, '&amp;', '&')
либо похожим способом:
SET @Output = replace(replace(replace(replace(replace(replace(replace(
@Output, '&quot;', '"'), '&lt;', '<'), '&gt;', '>'), '&apos;', ''''), '&#13;',
CHAR(0x0D)), '&#10;', CHAR(0x0A)),
'&amp;', '&')
30 сен 09, 16:23    [7725707]     Ответить | Цитировать Сообщить модератору
 Re: Конкатенация строк в nvarchar(max)  [new]
ResearchStudio
Member [заблокирован]

Откуда: страна ленивых программистов
Сообщений: 2506




десятичное, там обычно шестнадцатеричное число
30 сен 09, 16:42    [7725896]     Ответить | Цитировать Сообщить модератору
 Re: Конкатенация строк в nvarchar(max)  [new]
ResearchStudio
Member [заблокирован]

Откуда: страна ленивых программистов
Сообщений: 2506
&#13;
30 сен 09, 16:43    [7725903]     Ответить | Цитировать Сообщить модератору
Все форумы / Microsoft SQL Server Ответить