gpt4 book ai didi

sql - Oracle PL/SQL 中的字符串删除

转载 作者:行者123 更新时间:2023-12-02 01:46:20 25 4
gpt4 key购买 nike

我需要从输入字符串中删除某些关键字并返回新字符串。关键字存储在另一个表中,如 MR、MRS、DR、PVT、PRIVATE、CO、COMPANY、LTD、LIMITED 等。它们是两种关键字 LEADING - MR、MRS、DR 和 TRAILING - PVT、PRIVATE、CO、COMPANY, LTD、LIMITED 等。因此,如果关键字是 LEADING,那么我们必须从开头删除它,如果它是 TRAILING,那么我们必须从末尾删除它。例如- MR Jones MRS COMPANY 应该返回 JONES MRS 并且 MR MRS Jones PVT COMPANY 应该返回 JONES(如第一次迭代 MRPVT 将被修剪,然后单词将变为 MRS JONES PVT,在第二次迭代中它将变为 JONES。类似地,MR MRS Doe PVT COMPANY LTD 最终将返回 DOE

我必须通过 PL/SQL 来完成。我写了下面的代码,但如果开头或结尾有多个关键字,它就会删除所有关键字。当我循环遍历关键字游标时,如果关键字不在末尾并且循环已经迭代,那么我们不能重用该关键字来替换。请注意,结尾或开头都不能有 n 个关键字:

CREATE OR REPLACE FUNCTION replace_keyword (p_in_name IN VARCHAR2)
RETURN VARCHAR2
IS
l_name VARCHAR2 (4000);

CURSOR c
IS
SELECT *
FROM RSRV_KEY_LKUPS
WHERE ACTIVE = 'Y';
BEGIN
l_name := TRIM (p_in_name);

--Now inside the function we’ll loop through this cursor something like below and replace the value in the input name:

FOR rec IN c
LOOP
IF UPPER (rec.POSITION) = 'LEADING'
AND INSTR (UPPER (l_name), UPPER (rec.KEY_WORD || ' '), 1) > 0
THEN --Rule 3:remove leading name
DBMS_OUTPUT.PUT_LINE ('Value >>' || rec.KEY_WORD);
l_name := LTRIM (UPPER (l_name), rec.KEY_WORD || ' ');

ELSIF UPPER (rec.POSITION) = 'TRAILING'
AND INSTR (UPPER (l_name), UPPER (' ' || rec.KEY_WORD), -1) > 0
THEN --Rule 4:remove trailing name
DBMS_OUTPUT.PUT_LINE ('Value >>' || rec.KEY_WORD);
l_name := RTRIM (UPPER (l_name), ' ' || rec.KEY_WORD);
END IF;

l_name := l_name;
END LOOP;

l_name := REGEXP_REPLACE (l_name, '[[:space:]]{2,}', ' '); --Remove multiple spaces in a word and replace with single blank space
l_name := TRIM (l_name); --Remove the leading and trailing blank spaces
RETURN l_name;
EXCEPTION
WHEN OTHERS
THEN
raise_application_error (
-20001,
'An error was encountered - ' || SQLCODE || ' -ERROR- ' || SQLERRM);
END;
/

非常感谢您的帮助。

编辑示例输入 1

MR MRS Jones PVT COMPANY 

输出

JONES

示例输入 2

MR MRS Doe PVT COMPANY LTD 

输出

DOE

最佳答案

我认为它可以通过单个查询完成(如果您出于某种原因坚持,可以将其包装在 plsql 函数中):

Here is a sqlfiddle demo

with inpt as (select 'MR Jones MRS COMPANY' text from dual)
select listagg(t1.word, ' ') within group (order by ord) new_text
from (
select w.*, words.*,
sum(case when nvl(POSITION, 'TRAILING') = 'TRAILING' then 1 else 0 end) over(order by ord rows between unbounded preceding and current row) l,
sum(case when nvl(POSITION, 'LEADING') = 'LEADING' then 1 else 0 end) over(order by ord desc rows between unbounded preceding and current row) t
from
(select regexp_substr(inpt.text, '[^ ]+',1,level) word , level ord
from inpt
connect by level <= regexp_count(inpt.text, ' ') + 1) words left outer join RSRV_KEY_LKUPS w on w.KEY_WORD = words.word
) t1
where t1.t > 0 and t1.l > 0

编辑:解释:

'with' 子句只是将您的输入字符串作为列(并非真正必要)。

别名为“words”的内部选择是一种已知的将单词拆分为行的技术(请注意,我保持了 ord 列的顺序)。

现在我们可以将输入字符串的单词与表“RSRV_KEY_LKUPS”中的关键字进行左外连接,这将为我们提供输入中的每个单词,如果它应该是前导或尾随或空(如果它不存在) )

到目前为止,我们有(输入“MR Jones MRS COMPANY”):

KEY_WORD    POSITION    WORD    ORD 
-----------------------------------
MR LEADING MR 1
(null) (null) Jones 2
MRS LEADING MRS 3
COMPANY TRAILING COMPANY 4

现在是棘手的部分(也许有更好的方法)——我们需要以某种方式知道要删除哪个单词,它应该是所有的前导,直到“改变”,这意味着直到我们找到一个 null 或一个 TRAILING(顶部向下)和所有尾随,直到“变化”,这意味着空或前导(自下而上)。所以我使用了一个已知的 Technic 来计算累加总和,只要我们仍然归零,我们就需要删除该行(一旦我们得到“变化”,我们就会有一些值)。

就是这样,我们现在需要做的就是将行重新收集到一个新字符串中,因为从 11gr2 开始我们可以使用 LISTAGG 来完成此操作

关于sql - Oracle PL/SQL 中的字符串删除,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25504587/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com