String Oracle-字符串-标点符号格式化函数
我有一个String Oracle-字符串-标点符号格式化函数,string,oracle,function,plsql,punctuation,String,Oracle,Function,Plsql,Punctuation,我有一个函数,它将字符串中的多个(连续)水平空格替换为单个水平空格 e、 g 功能如下: CREATE OR REPLACE FUNCTION CP_RDN_PUNCT( INS VARCHAR2) RETURN VARCHAR2 AS OUTSTR VARCHAR2(4000); STR VARCHAR2(4000); BEGIN STR := INS; WHILE (INSTR(STR,' ',1) > 0 ) LOOP OUTSTR := OUTSTR || '
函数
,它将字符串
中的多个(连续)水平空格替换为单个水平空格
e、 g
功能如下:
CREATE OR REPLACE FUNCTION CP_RDN_PUNCT(
INS VARCHAR2)
RETURN VARCHAR2
AS
OUTSTR VARCHAR2(4000);
STR VARCHAR2(4000);
BEGIN
STR := INS;
WHILE (INSTR(STR,' ',1) > 0 )
LOOP
OUTSTR := OUTSTR || ' ' || SUBSTR(STR,1,INSTR(STR,' ',1) - 1);
STR := TRIM(BOTH ' ' FROM SUBSTR(STR,INSTR(STR,' ',1)));
END LOOP;
OUTSTR := OUTSTR || ' ' || TRIM(STR);
RETURN TRIM(OUTSTR);
END CP_RDN_PUNCT;
不过,我想进一步介绍一下这个函数
,这样它就能够纠正基本的标点格式(逗号、句号和括号)。但是,函数继续删除多个(连续的)水平空间很重要
比如,
如果STR\u ORIG='Hello,Marc'
输出将变成'Hello,Marc'
如果STR\u ORIG='Hello.Marc'
输出将变成'Hello。Marc'
如果STR_ORIG='Hello(Marc)
输出将变成'Hello(Marc)
我想使用的规则相当基本:
Comma;...............One HORIZONTAL SPACE after a Comma.
No HORIZONTAL SPACE before a Comma.
Full Stop;...........One HORIZONTAL SPACE after a Full Stop.
No HORIZONTAL SPACE before a Full Stop.
Open Parenthesis;....No HORIZONTAL SPACE after an Open Parenthesis.
One HORIZONTAL SPACE before an Open Parenthesis.
Closed Parenthesis;..One HORIZONTAL SPACE after an Closed Parenthesis*.
No HORIZONTAL SPACE before an Closed Parenthesis.
*注意:当右括号后面直接出现逗号或句号时,它将使用“无水平空间
”规则,而不是“一水平空间
”规则
我相信函数
是解决此问题的最佳方法(我已经使用纯SQL(REG\u EXP
)进行了探索,但代码开始变得非常混乱-主要是因为数据不一致)。此外,如果我想在将来添加其他规则(例如下划线规则),我假设函数
更易于维护。然而,像往常一样,我愿意听取专业人士的建议
非常感谢。您可以使用
REGEXP
编写函数,而不是使用INSTR
,SUBSTR
<强>注:此函数不考虑在同一字符串中出现多种类型的模式。所以,如果“,”和“,”都出现,它将不起作用。因此,您可以自己编写所需的所有转换代码、
EXCEPTION
处理等,以涵盖此类场景。我已经给了你如何做的想法。对于类似PL/SQL的代码,您可能必须使用IF-THEN
或CASE
块重写,正如我在with
子句中编码的那样
CREATE OR REPLACE FUNCTION CP_RDN_PUNCT(
inp_pattern VARCHAR2)
RETURN VARCHAR2
AS
outstr VARCHAR2(4000);
BEGIN
with reg ( pattern, regex ,replacement ) AS
(
select ',' , ' *, *', ', ' FROM DUAL UNION ALL
select '.' , ' *\. *', '. ' FROM DUAL UNION ALL
select '(' , ' *\( *', ' (' FROM DUAL
)
SELECT
TRIM(regexp_replace(rep,' *\) *',') ') ) INTO outstr
FROM
(
SELECT
regexp_replace(inp_pattern,regex,replacement) rep
FROM
reg
WHERE
inp_pattern LIKE '%'
|| pattern
|| '%'
);
RETURN outstr;
END;
/
与使用
INSTR
,SUBSTR
相比,您可以使用REGEXP
编写函数
<强>注:此函数不考虑在同一字符串中出现多种类型的模式。所以,如果“,”和“,”都出现,它将不起作用。因此,您可以自己编写所需的所有转换代码、
EXCEPTION
处理等,以涵盖此类场景。我已经给了你如何做的想法。对于类似PL/SQL的代码,您可能必须使用IF-THEN
或CASE
块重写,正如我在with
子句中编码的那样
CREATE OR REPLACE FUNCTION CP_RDN_PUNCT(
inp_pattern VARCHAR2)
RETURN VARCHAR2
AS
outstr VARCHAR2(4000);
BEGIN
with reg ( pattern, regex ,replacement ) AS
(
select ',' , ' *, *', ', ' FROM DUAL UNION ALL
select '.' , ' *\. *', '. ' FROM DUAL UNION ALL
select '(' , ' *\( *', ' (' FROM DUAL
)
SELECT
TRIM(regexp_replace(rep,' *\) *',') ') ) INTO outstr
FROM
(
SELECT
regexp_replace(inp_pattern,regex,replacement) rep
FROM
reg
WHERE
inp_pattern LIKE '%'
|| pattern
|| '%'
);
RETURN outstr;
END;
/
我可以想到的另一种方法是使用
关联数组
来存储模式和替换,而不是普通的sql。然后在循环中对字符串应用每个变换
CREATE OR REPLACE FUNCTION cp_rdn_punct2 (
inp_pattern VARCHAR2
) RETURN VARCHAR2 AS
v_outstr VARCHAR2(1000) := inp_pattern;
TYPE v_astype IS
TABLE OF VARCHAR2(40) INDEX BY VARCHAR(40);
v_pat v_astype;
v_idx VARCHAR2(40);
BEGIN
v_pat(' *, *' ) := ', ';
v_pat(' *\. *') := '. ';
v_pat(' *\( *') := ' (';
v_pat(' *\) *') := ') ';
v_idx := v_pat.first;
WHILE v_idx IS NOT NULL LOOP
v_outstr := regexp_replace(v_outstr,v_idx,v_pat(v_idx) );
v_idx := v_pat.next(v_idx);
END LOOP;
RETURN v_outstr;
END;
/
我可以想到的另一种方法是使用
关联数组
来存储模式和替换,而不是普通的sql。然后在循环中对字符串应用每个变换
CREATE OR REPLACE FUNCTION cp_rdn_punct2 (
inp_pattern VARCHAR2
) RETURN VARCHAR2 AS
v_outstr VARCHAR2(1000) := inp_pattern;
TYPE v_astype IS
TABLE OF VARCHAR2(40) INDEX BY VARCHAR(40);
v_pat v_astype;
v_idx VARCHAR2(40);
BEGIN
v_pat(' *, *' ) := ', ';
v_pat(' *\. *') := '. ';
v_pat(' *\( *') := ' (';
v_pat(' *\) *') := ') ';
v_idx := v_pat.first;
WHILE v_idx IS NOT NULL LOOP
v_outstr := regexp_replace(v_outstr,v_idx,v_pat(v_idx) );
v_idx := v_pat.next(v_idx);
END LOOP;
RETURN v_outstr;
END;
/
太棒了,谢谢你,考希克·纳亚克-我很快会测试的。非常感谢。不幸的是,这可以编译,但经过测试,它会导致
ORA-01422:exact fetch返回的行数超过请求的行数。发布前测试-多好的概念啊!:-)太棒了,谢谢你,考希克·纳亚克-我很快会测试的。非常感谢。不幸的是,这可以编译,但经过测试,它会导致ORA-01422:exact fetch返回的行数超过请求的行数。发布前测试-多好的概念啊!:-)这太棒了,@Kaushik Nayak!我真的很感谢你抽出时间来做这件事——非常感谢。这件事太棒了,@Kaushik Nayak!我真的很感谢你抽出时间来做这件事,非常感谢。