PLSQL - 连接两个字符串并根据条件拆分为 3 个字符串

PLSQL - Concatenate two strings and split into 3 strings on condition

在 PL-SQL 中,我想将取自 2 列(地址行 1、地址行 2,每个最多 45 个字符)的两个字符串连接成 3 个字符串(地址行 1、地址行 2、 address line 3, maximum 34 characters each) 基于中间没有单词的条件。例如:

如果地址第 1 行包含:

1, abc park, def chowk, ghi marg c-123 street

地址第 2 行包含:

city mumbai, pin - 435353

结合编号显示 34 个字符所在的位置:

         1111111111222222222233333         1111111111222222222233333
12345678901234567890123456789012341234567890123456789012345678901234123
1, abc park, def chowk, ghi marg c-123 street city mumbai, pin - 435353

结果应该是这样的

Add1(最多 34 个字符):

1, abc park, def chowk, ghi marg

Add2(最多 34 个字符):

c-123 street city mumbai,

Add3(最多 34 个字符):

pin - 435353

我遇到了同样的问题,我写了这个函数,它将文本分成固定长度的行而不截断单词。

pi_text:您展开的文字

pi_max_line : 您要拆分的行长度

CREATE OR REPLACE FUNCTION wrap_to_paragraph(pi_text          VARCHAR2,
                                             pi_max_line      PLS_INTEGER,
                                             pi_end_paragraph VARCHAR2 DEFAULT CHR(10)) RETURN VARCHAR2 IS

  TYPE paragraph_tabletype_aat IS TABLE OF VARCHAR2(100) INDEX BY BINARY_INTEGER;

  l_loc_para  paragraph_tabletype_aat;
  l_loc_lines INTEGER;
  l_return    VARCHAR2(32767);

  PROCEDURE to_paragraph(pi_text_in          IN VARCHAR2,
                         pi_line_length      IN INTEGER,
                         po_paragraph_out    IN OUT paragraph_tabletype_aat,
                         pio_num_lines_out   IN OUT INTEGER,
                         pi_word_break_at_in IN VARCHAR2 := ' ') IS

    l_len_text       INTEGER := LENGTH(pi_text_in);
    l_line_start_loc INTEGER := 1;
    l_line_end_loc   INTEGER := 1;
    l_last_space_loc INTEGER;
    l_curr_line      VARCHAR2(100);
    l_replace_string VARCHAR2(100) := NULL;

    PROCEDURE set_replace_string IS
    BEGIN
      l_replace_string := RPAD('@', LENGTH(pi_word_break_at_in), '@');
    END set_replace_string;

    PROCEDURE find_last_delim_loc(pi_line_in IN VARCHAR2,
                                  po_loc_out OUT INTEGER) IS
      l_line VARCHAR2(1000) := pi_line_in;
    BEGIN
      IF pi_word_break_at_in IS NOT NULL
      THEN
        l_line := translate(pi_line_in, pi_word_break_at_in, l_replace_string);
      END IF;
      po_loc_out := INSTR(l_line, '@', -1);
    END find_last_delim_loc;

  BEGIN
    set_replace_string;

    IF l_len_text IS NULL
    THEN
      pio_num_lines_out := 0;
    ELSE
      pio_num_lines_out := 1;

      LOOP
        EXIT WHEN l_line_end_loc > l_len_text;
        l_line_end_loc := LEAST(l_line_end_loc + pi_line_length, l_len_text + 1);

        /* get the next possible line of text */
        l_curr_line := SUBSTRB(pi_text_in || ' ', l_line_start_loc, pi_line_length + 1);

        /* find the last space in this section of the line */
        find_last_delim_loc(l_curr_line, l_last_space_loc);

        /* When NO spaces exist, use the full current line*/
        /* otherwise, cut the line at the space.          */
        IF l_last_space_loc > 0
        THEN
          l_line_end_loc := l_line_start_loc + l_last_space_loc;
        END IF;

        IF INSTR(l_curr_line, pi_end_paragraph) > 0
        THEN
          l_line_end_loc := l_line_start_loc + INSTR(l_curr_line, pi_end_paragraph) + 1;
        END IF;

        /* Add this line to the paragraph */
        po_paragraph_out(pio_num_lines_out) := REPLACE(SUBSTRB(pi_text_in,
                                                               l_line_start_loc,
                                                               l_line_end_loc - l_line_start_loc),
                                                       pi_end_paragraph);

        pio_num_lines_out := pio_num_lines_out + 1;
        l_line_start_loc  := l_line_end_loc;
      END LOOP;

      pio_num_lines_out := pio_num_lines_out - 1;

    END IF;
  END to_paragraph;

BEGIN

  /* Return original */
  IF (pi_max_line = 0 OR pi_max_line > 99)
  THEN
    RETURN pi_text;
  END IF;

  /* Build each paragraph in record */
  to_paragraph(pi_text, pi_max_line, l_loc_para, l_loc_lines);

  /* Extract Result */
  FOR i IN 1 .. l_loc_lines
  LOOP
    l_return := l_return || l_loc_para(i) || pi_end_paragraph;
  END LOOP;

  RETURN TRIM(CHR(10) FROM l_return);

END wrap_to_paragraph;

REGEXP_SUBSTR() 可以帮你解决这个问题。正如我在对您的原始 post 的评论中所说,您的文字说不要中断一个词,但您的示例显示 ADD3 在最后一个 comma/space 之后中断,而不仅仅是 space 所以您需要进一步定义您的规则(也许当它只是最后一个逗号之后的最后一部分时?)。无论如何,坚持你写的内容,正则表达式给出最多 34 个字符的第一次、第二次或第三次出现,后面跟着一个不是白色的字符 space,然后是白色 space字符或行尾。

SQL> with tbl(addr) as (
     select '1, abc park, def chowk, ghi marg c-123 street city mumbai, pin - 435353'
     from dual
   )
   select regexp_substr(addr, '(.{0,34}\S)(\s|$)', 1, 1) add1,
          regexp_substr(addr, '(.{0,34}\S)(\s|$)', 1, 2) add2,
          regexp_substr(addr, '(.{0,34}\S)(\s|$)', 1, 3) add3
   from tbl;

ADD1                              ADD2                             ADD3
--------------------------------- -------------------------------- ------
1, abc park, def chowk, ghi marg  c-123 street city mumbai, pin -  435353

SQL>