2015-12-02 4 views
3

Скажем, у меня есть эта таблица:Concatenation слишком долго

ID|Col1|Col2|Col3 

1|Text that has 4000 chars|Text2 that has 4000 chars|Text3 that has 4000 chars 

2|Text4 that has 4000 chars|Text5 that has 4000 chars|Text6 that has 4000 chars 

3|Text7 that has 4000 chars|Text8 that has 4000 chars|Text9 that has 4000 chars 

Я использую listagg так:

SELECT id, 
     listagg(col1||col2||col3, ',') within group (order by id) 
FROM table; 

И я встретив ошибку:

ORA-01489: result of string concatenation is too long 

При исследовании, Я узнал, что использование xmlagg может сделать трюк (link), но затем поняла, что реальная проблема кроется в конкатенации col1, col2 и col3, поскольку он ограничен только 4000 символами, поэтому xmlagg все равно вернет ту же ошибку.

Неужели кто-нибудь еще это понял? Или нет обходного пути для этого? (link)

Update:

Я обновил выборочные значения на столе только, чтобы быть ясно (для г-н Кумар понять), и мой ожидаемый результат должен быть что-то вроде:

ID | Agg 
1 | Text that has 4000 charsText2 that has 4000 charsText3 that has 4000 chars 
2 | Text4 that has 4000 charsText5 that has 4000 charsText6 that has 4000 chars 
3 | Text7 that has 4000 charsText8 that has 4000 charsText9 that has 4000 chars 

Что, по-видимому, не работает.

+0

«*, но потом понял, что реальная проблема заключается в конкатенации col1 , col2 и col3, так как он ограничен только 4000 символами, поэтому xmlagg все равно вернет ту же ошибку. * «Нет. Вам нужно объединить вывод XMLAGG каждого столбца. Например, 'rtrim (xmlagg (xmlelement (e, col1, ','). Extract ('// text()') order by col1) .GetClobVal(), ',') || rtrim (xmlagg (xmlelement (xmlagg) e, col2, ','). extract ('// text()') order by col2) .GetClobVal(), ',') ' –

+0

Нет. Это вернет: Текст на col1 row1, Текст на col1 row2, Текст на col1 row3 Текст на col2 row1, Текст на col2 row2, Текст на col2 row3 Текст на col2 row3 Текст на col3 row1, Текст на col3 row2, Текст на col3 row3 Вместо: Текст на col1 row1, Текст на col2 row1, Текст на col3 row1 Текст на col1 row2, Текст на col2 row2, Текст на col2 row2 Текст на col3 row2 Текст на col1 row3, Текст на col2 row3, Текст на col3 row3 – superigno

+0

Я пробовал он и он вернул значения, которые я ожидал, чтобы они вернулись, как упоминалось в моем предыдущем комментарии – superigno

ответ

1

Вы можете сделать это намного проще, поскольку Oracle представила SQL Semantics and LOBs некоторое время назад.

SELECT ID, TO_CLOB(col1) || col2 || col3 AS very_long_text 
FROM TABLE; 

Первый элемент || оператора должен быть CLOB, то он работает.

+0

XMLAGG также возвращает CLOB, поэтому нет предела varchar2 в 4000 байт. –

+0

Я получаю это, хотя: ORA-22835: Буфер слишком мал для CLOB для CHAR или BLOB для RAW преобразования (текущая: 8002, максимальная: 4000) – superigno

+0

Используя это: ВЫБЕРИТЕ идентификатор, listagg (TO_CLOB (col1) | | col2 || col3, ',') внутри группы (порядок по id) FROM table; – superigno

1

Я, наконец, получил его на работу. Я сделал это, чтобы собрать столбцы перед конкатенацией, GROUP, как предложил г-н Кумар, и затем заполнить их снова, чтобы исправить порядок. Вот как:

WITH agg_tbl AS 
(
SELECT id, 
     rtrim(xmlagg(xmlelement(e,col1,',').extract('//text()').GetClobVal(),',')||rtrim(xmlagg(xmlelement(e,col1,',').extract('//text()').GetClobVal(),',')||rtrim(xmlagg(xmlelement(e,col1,',').extract('//text()').GetClobVal(),',') long_text 
FROM table 
GROUP BY col1 
) 
SELECT rtrim(xmlagg(xmlelement(e,long_text,chr(13)).extract('//text()').GetClobVal(),',') agg_value 
FROM agg_tbl; 

Таким образом, вместо этого:

agg_value 
Text that has 4000 charsText4 that has 4000 charsText7 that has 4000 chars 
Text2 that has 4000 charsText5 that has 4000 charsText8 that has 4000 chars 
Text3 that has 4000 charsText6 that has 4000 charsText9 that has 4000 chars 

Я сейчас получаю нужный мне результат:

agg_value 
Text that has 4000 charsText2 that has 4000 charsText3 that has 4000 chars 
Text4 that has 4000 charsText5 that has 4000 charsText6 that has 4000 chars 
Text7 that has 4000 charsText8 that has 4000 charsText9 that has 4000 chars 
+0

Рад, что вы все поняли! +1 Вы могли бы отметить свой собственный ответ как правильный ответ, тогда я удалю свою. Это так или иначе ниспровергнуто! –

+0

Спасибо @LalitKumarB! ура – superigno