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>
在 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>