Как разбить строку без усечения слов в PL / SQL?

У меня есть таблица Data с полем Note которое содержит длинную строку. Я хотел бы разделить содержимое каждой из этих строк каждые 30 символов без усечения слов. Это означает, что если разделение собирается усечь слово, оно должно разделиться перед этим словом и перезапустить процесс разделения из следующего:

Пример использования разделения каждого 7 символов

Данные

--------------------------
| Id | Note              |
--------------------------
|  1 |I am dumb using SQL|
--------------------------
... more rows ...
--------------------------

Результат

----------------
| Id | Note    |    
----------------
|  1 |I am     |
----------------
|  2 |dumb     |
----------------
|  3 |using    |
----------------
|  4 |SQL      |
----------------

Обратите внимание, как происходит первое разделение: первые 7 символов - это I am du потому что разделение на седьмое усекает слово « dumb , разделение применяется раньше, и в результате получается « I am .

Некоторый код, чтобы повторить пример и мои попытки решить проблему:

CREATE TABLE Data (ID, NOTA);
INSERT INTO Data (ID, NOTA)
VALUES (10, 'NEL MEZZO DEL CAMMIN DI NOSTRA VITA MI RITROVAI IN UNA SELVA OSCURA');

SELECT 
ID, rownum AS rn
                ,trim(regexp_substr(NOTA,'.{1,60}( |$)',1,rownum)) AS SPLIT_NOTA
FROM Data  connect by rownum <= ceil(length(NOTA)/60)

Всего 2 ответа


Предполагая, что вы не хотели бы сокращать более длинные слова:

([^ ]{1}.{1,6}(?= ))|([^
 ]{1,})

Объяснение основных групп регулярного выражения:

([^ ]{1}.{1,6}(?= )) - один не пробел, за которым следуют до 6 символов, после которых есть пробел (положительный взгляд).

([^ ]{1,}) - один или несколько не-пробелов, не-новых строк. Эта часть регулярного выражения отвечает за покрытие более длинных слов, чем 7 (или 30) символов, и за покрытие последнего слова из строки.

Вы должны заменить 6 на n-1 где n - это число символов, которое может уместиться без усечения (в вашем случае - 7 или 30). Я разработал это регулярное выражение с помощью Notepad ++, и я не могу обещать, что он будет работать в вашей среде.


Я предполагаю, что вы пытаетесь получить пример, который обрабатывает несколько строк?

with tbl_source(id, txt) as (
  select 1, 'I am dumb using SQL'     from dual union all
  select 2, 'This is a test of row 2' from dual
),
tbl_main(id, rownbr, txt, txt_length) as (
select id, level as rownbr, trim(regexp_substr(txt,'.{1,7}( |$)',1,level)) as txt,
       length(trim(regexp_substr(txt,'.{1,7}( |$)',1,level))) txt_length
       from tbl_source
       connect by level <= ceil(length(txt)/7)+1
       and prior txt = txt
       and prior sys_guid() is not null 
)
select id, rownbr, txt, txt_length
from tbl_main
where txt is not null
order by id, rownbr;

Выход:

        ID     ROWNBR TXT                     TXT_LENGTH
---------- ---------- ----------------------- ----------
         1          1 I am                             4
         1          2 dumb                             4
         1          3 using                            5
         1          4 SQL                              3
         2          1 This is                          7
         2          2 a test                           6
         2          3 of row                           6
         2          4 2                                1

8 rows selected.

Есть идеи?

10000