PLSQL - 连接两个字符串并在条件下分成3个字符串

时间:2017-06-13 14:42:26

标签: string plsql concatenation divide

在PL-SQL中,我想将两列中的两个字符串(地址行1,地址行2,每行最多45个字符)连接成3个字符串(地址行1,地址行2,地址行3,最大值34)每个字符都基于不应该在中间剪切的条件。例如:

如果地址行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

2 个答案:

答案 0 :(得分:1)

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

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;

答案 1 :(得分:0)

REGEXP_SUBSTR()可用于为您解决此问题。正如我在您对原始帖子的评论中所说的那样,您的文字说不要破坏一个字,但是您的示例显示ADD3在最后一个逗号/空格后突破,而不仅仅是空格,因此您需要进一步定义规则(也许当它只是最后一个逗号之后的最后一节?)。无论如何,坚持你写的东西,正则表达式给出第一次,第二次或第三次出现最多34个字符,后跟一个不是空格的字符,后跟一个空格字符或行的结尾。

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>