как объединить строки? - PullRequest
       14

как объединить строки?

5 голосов
/ 11 января 2012

Я нахожусь на Oracle 10g и имею следующую структуру таблицы: Я бы, пункт

Я хочу сгруппировать по идентификатору и объединить абзацы. Каждый абзац может быть 1500 символов или более.

Когда я пробую функцию wm_concat, она жалуется, что строковый буфер слишком мал. Я на самом деле пробовал многие примеры на веб-сайте Oracle, и все они терпят неудачу с ошибкой, что строковый буфер слишком мал.

select id, wm_concat(paragraph) from paragraphs group by id

как мне это решить?

1 Ответ

3 голосов
/ 11 января 2012

Итак, я предполагаю, что ошибка ORA-06502, и я понимаю, как вы думаете, что это не относится к вам в этой ситуации.

Однако это вина wm_concat. Эта функция ограничена максимальной длиной Oracle в varchar в PL \ SQL, равной 32 767 и 4000 в стандартном SQL. К сожалению, я предполагаю, что из-за способа, которым работает wm_concat, или из-за каких-либо более низких ограничений в функции, или из-за того, что вы используете его в выборе, вы не можете получить что-либо вблизи верхнего предела.

Существует еще одна опция, stragg, функция агрегирования строк Тома Кайта. Если мы посмотрим на следующее сравнение между ними, то увидим, что они работают почти одинаково и что предел обоих составляет длину около 4000, то есть стандартный максимум SQL. stragg немного быстрее, возможно, из-за кэширования.

SQL> set serveroutput on
SQL>
SQL> create table tmp_test ( a varchar2(30) );

Table created.

SQL> insert into tmp_test
  2   select object_name
  3     from all_objects
  4          ;

81219 rows created.

SQL>  commit ;

Commit complete.

SQL>
SQL> declare
  2
  3    i integer := 1;
  4    k number(10);
  5    v_stragg varchar2(32767);
  6    v_test varchar2(32767) := '';
  7    start_time timestamp;
  8
  9  begin
 10
 11    select count(*)
 12      into k
 13      from tmp_test;
 14
 15    for i in 1 .. k loop
 16      start_time := systimestamp;
 17      begin
 18
 19        select wm_concat(a) into v_test
 20          from tmp_test
 21         where rownum < i;
 22
 23      exception when others then
 24        dbms_output.put_line('wm_concat: ' || length(v_test));
 25        dbms_output.put_line(systimestamp - start_time);
 26        exit;
 27     end;
 28    end loop;
 29
 30    for i in 1 .. k loop
 31      start_time := systimestamp;
 32
 33      select stragg(a) into v_test
 34        from tmp_test
 35       where rownum < i;
 36
 37      if v_test = 'OVERFLOW' then
 38        dbms_output.put_line('stragg: ' || length(v_stragg));
 39        dbms_output.put_line(systimestamp - start_time);
 40        exit;
 41      else v_stragg := v_test;
 42      end if;
 43    end loop;
 44  end;
 45  /
wm_concat: 3976
+000000000 00:00:00.005886000
stragg: 3976
+000000000 00:00:00.005707000

PL/SQL procedure successfully completed.

Что касается решения, я боюсь, что вы не можете. Как только вы достигнете этого предела, вот и все. Вам нужно будет найти другой способ выполнить агрегацию или спросить себя, действительно ли вам это нужно

...