Oracle:如何使用 column1 中的精确值搜索和替换 column2 中的文本?
Oracle: How to search and replace the text in column2 with exact value from the column1?
我在 table 中有 2 个文本列。要求是比较这两列并检查是否有任何文本匹配并将其替换为第一列中的文本。我们要注意案件。
CREATE TABLE search_text(
id NUMBER(20,0),
text1 varchar2(1000),
text2 varchar2(1000));
INSERT INTO search_text VALUES
(
100,
'Inband signaling used in transmission that reduces the available user bandwidth from 1.544 to 1.536 Mbps.',
'USER Bandwidth >inband Signaling< (TRansmission>'
);
替换后 text2 列的预期结果是
"user bandwidth >Inband signaling< (transmission>"
更新search_text
设置文本 1 = 文本 2,
文本 2= 文本 1
但在这样做之前,请创建备份,您可能会丢失信息。这在 SQL 服务器中工作,因此它肯定会在 oracle 中工作。
我不知道如何在 SQL 中做到这一点,但是 - 如果 PL/SQL 对你没问题,看看这是否有帮助。
Table内容:
SQL> select * from search_text;
ID TEXT1 TEXT2
---- ---------------------------------------- ----------------------------------------
100 Inband signaling used in transmission th USER Bandwidth >inband Signaling< (TRans
at reduces the available user bandwidth mission>
from 1.544 to 1.536 Mbps.
功能:嵌套循环,逐字比较text1
和text2
字符串。如果它们匹配(请注意 lower
函数以及 regexp_substr
删除 >
、(
等),执行替换。
SQL> create or replace function f_replace (par_id in number)
2 return varchar2
3 is
4 l_text search_text.text2%type;
5 l_fir varchar2(100);
6 l_sec varchar2(100);
7 begin
8 select text2
9 into l_text
10 from search_text
11 where id = par_id;
12
13 for cur_fir in (select regexp_substr(text1, '[^ ]+', 1, level) val
14 from search_text
15 where id = par_id
16 connect by level <= regexp_count(text1, ' ') + 1
17 )
18 loop
19 for cur_sec in (select regexp_substr(text2, '[^ ]+', 1, level) val
20 from search_text
21 where id = par_id
22 connect by level <= regexp_count(text2, ' ') + 1
23 )
24 loop
25 l_fir := regexp_substr(cur_fir.val, '\w+');
26 l_sec := regexp_substr(cur_sec.val, '\w+');
27 l_text := case when lower(l_sec) = lower(l_fir)
28 then replace(l_text, l_sec, l_fir)
29 else l_text
30 end;
31 end loop;
32 end loop;
33
34 return l_text;
35 end;
36 /
Function created.
测试:
SQL> select f_replace(100) result from dual;
RESULT
------------------------------------------------------------------
user bandwidth >Inband signaling< (transmission>
SQL>
仅使用 SQL。分层查询将字符串拆分成多行,逐字替换。然后聚合函数获取最后一行,其中包含所有单词的累积替换:
with t (id, word, text1, text2, replaced_text2, lvl) as
(
select id,
regexp_substr(text1, '[[:alpha:]\'']+', 1, 1, 'i'),
text1,
text2,
regexp_replace(text2,
'([^[:alpha:]]+|^)' || regexp_substr(text1, '[[:alpha:]\'']+', 1, 1, 'i') || '([^[:alpha:]]+|$)',
'' || regexp_substr(text1, '[[:alpha:]\'']+', 1, 1, 'i') || '',
1, 1, 'i'),
1 lvl
from search_text
union all
select s.id,
regexp_substr(s.text1, '[[:alpha:]\'']+', 1, t.lvl + 1, 'i'),
s.text1,
s.text2,
regexp_replace(t.replaced_text2,
'([^[:alpha:]]+|^)' || regexp_substr(s.text1, '[[:alpha:]\'']+', 1, t.lvl + 1, 'i') || '([^[:alpha:]]+|$)',
'' || regexp_substr(s.text1, '[[:alpha:]\'']+', 1, t.lvl + 1, 'i') || '',
1, 0, 'i'),
t.lvl + 1
from search_text s, t
where t.id = s.id
and regexp_count(s.text1, '[[:alpha:]\'']+') >= t.lvl + 1
)
select t.id,
t.text1,
t.text2,
max(t.replaced_text2) keep (dense_rank first order by t.lvl desc) replaced_text2
from t
group by t.id, t.text1, t.text2
order by id;
示例执行:
FSITJA@db01> with t (id, word, text1, text2, replaced_text2, lvl) as
2 (
3 select id,
4 regexp_substr(text1, '[[:alpha:]\'']+', 1, 1, 'i'),
5 text1,
6 text2,
7 regexp_replace(text2,
8 '([^[:alpha:]]+|^)' || regexp_substr(text1, '[[:alpha:]\'']+', 1, 1, 'i') || '([^[:alpha:]]+|$)',
9 '' || regexp_substr(text1, '[[:alpha:]\'']+', 1, 1, 'i') || '',
10 1, 1, 'i'),
11 1 lvl
12 from search_text
13 union all
14 select s.id,
15 regexp_substr(s.text1, '[[:alpha:]\'']+', 1, t.lvl + 1, 'i'),
16 s.text1,
17 s.text2,
18 regexp_replace(t.replaced_text2,
19 '([^[:alpha:]]+|^)' || regexp_substr(s.text1, '[[:alpha:]\'']+', 1, t.lvl + 1, 'i') || '([^[:alpha:]]+|$)',
20 '' || regexp_substr(s.text1, '[[:alpha:]\'']+', 1, t.lvl + 1, 'i') || '',
21 1, 0, 'i'),
22 t.lvl + 1
23 from search_text s, t
24 where t.id = s.id
25 and regexp_count(s.text1, '[[:alpha:]\'']+') >= t.lvl + 1
26 )
27 select t.id,
28 t.text1,
29 t.text2,
30 max(t.replaced_text2) keep (dense_rank first order by t.lvl desc) replaced_text2
31 from t
32 group by t.id, t.text1, t.text2
33 order by id;
ID TEXT1 TEXT2 REPLACED_TEXT2
---- ---------------------------------------- ---------------------------------------- ----------------------------------------
100 Inband signaling used in transmission th USER Bandwidth >inband Signaling< (TRans user bandwidth >Inband signaling< (trans
at reduces the available user bandwidth mission> mission>
from 1.544 to 1.536 Mbps.
我在 table 中有 2 个文本列。要求是比较这两列并检查是否有任何文本匹配并将其替换为第一列中的文本。我们要注意案件。
CREATE TABLE search_text(
id NUMBER(20,0),
text1 varchar2(1000),
text2 varchar2(1000));
INSERT INTO search_text VALUES
(
100,
'Inband signaling used in transmission that reduces the available user bandwidth from 1.544 to 1.536 Mbps.',
'USER Bandwidth >inband Signaling< (TRansmission>'
);
替换后 text2 列的预期结果是
"user bandwidth >Inband signaling< (transmission>"
更新search_text 设置文本 1 = 文本 2, 文本 2= 文本 1 但在这样做之前,请创建备份,您可能会丢失信息。这在 SQL 服务器中工作,因此它肯定会在 oracle 中工作。
我不知道如何在 SQL 中做到这一点,但是 - 如果 PL/SQL 对你没问题,看看这是否有帮助。
Table内容:
SQL> select * from search_text;
ID TEXT1 TEXT2
---- ---------------------------------------- ----------------------------------------
100 Inband signaling used in transmission th USER Bandwidth >inband Signaling< (TRans
at reduces the available user bandwidth mission>
from 1.544 to 1.536 Mbps.
功能:嵌套循环,逐字比较text1
和text2
字符串。如果它们匹配(请注意 lower
函数以及 regexp_substr
删除 >
、(
等),执行替换。
SQL> create or replace function f_replace (par_id in number)
2 return varchar2
3 is
4 l_text search_text.text2%type;
5 l_fir varchar2(100);
6 l_sec varchar2(100);
7 begin
8 select text2
9 into l_text
10 from search_text
11 where id = par_id;
12
13 for cur_fir in (select regexp_substr(text1, '[^ ]+', 1, level) val
14 from search_text
15 where id = par_id
16 connect by level <= regexp_count(text1, ' ') + 1
17 )
18 loop
19 for cur_sec in (select regexp_substr(text2, '[^ ]+', 1, level) val
20 from search_text
21 where id = par_id
22 connect by level <= regexp_count(text2, ' ') + 1
23 )
24 loop
25 l_fir := regexp_substr(cur_fir.val, '\w+');
26 l_sec := regexp_substr(cur_sec.val, '\w+');
27 l_text := case when lower(l_sec) = lower(l_fir)
28 then replace(l_text, l_sec, l_fir)
29 else l_text
30 end;
31 end loop;
32 end loop;
33
34 return l_text;
35 end;
36 /
Function created.
测试:
SQL> select f_replace(100) result from dual;
RESULT
------------------------------------------------------------------
user bandwidth >Inband signaling< (transmission>
SQL>
仅使用 SQL。分层查询将字符串拆分成多行,逐字替换。然后聚合函数获取最后一行,其中包含所有单词的累积替换:
with t (id, word, text1, text2, replaced_text2, lvl) as
(
select id,
regexp_substr(text1, '[[:alpha:]\'']+', 1, 1, 'i'),
text1,
text2,
regexp_replace(text2,
'([^[:alpha:]]+|^)' || regexp_substr(text1, '[[:alpha:]\'']+', 1, 1, 'i') || '([^[:alpha:]]+|$)',
'' || regexp_substr(text1, '[[:alpha:]\'']+', 1, 1, 'i') || '',
1, 1, 'i'),
1 lvl
from search_text
union all
select s.id,
regexp_substr(s.text1, '[[:alpha:]\'']+', 1, t.lvl + 1, 'i'),
s.text1,
s.text2,
regexp_replace(t.replaced_text2,
'([^[:alpha:]]+|^)' || regexp_substr(s.text1, '[[:alpha:]\'']+', 1, t.lvl + 1, 'i') || '([^[:alpha:]]+|$)',
'' || regexp_substr(s.text1, '[[:alpha:]\'']+', 1, t.lvl + 1, 'i') || '',
1, 0, 'i'),
t.lvl + 1
from search_text s, t
where t.id = s.id
and regexp_count(s.text1, '[[:alpha:]\'']+') >= t.lvl + 1
)
select t.id,
t.text1,
t.text2,
max(t.replaced_text2) keep (dense_rank first order by t.lvl desc) replaced_text2
from t
group by t.id, t.text1, t.text2
order by id;
示例执行:
FSITJA@db01> with t (id, word, text1, text2, replaced_text2, lvl) as
2 (
3 select id,
4 regexp_substr(text1, '[[:alpha:]\'']+', 1, 1, 'i'),
5 text1,
6 text2,
7 regexp_replace(text2,
8 '([^[:alpha:]]+|^)' || regexp_substr(text1, '[[:alpha:]\'']+', 1, 1, 'i') || '([^[:alpha:]]+|$)',
9 '' || regexp_substr(text1, '[[:alpha:]\'']+', 1, 1, 'i') || '',
10 1, 1, 'i'),
11 1 lvl
12 from search_text
13 union all
14 select s.id,
15 regexp_substr(s.text1, '[[:alpha:]\'']+', 1, t.lvl + 1, 'i'),
16 s.text1,
17 s.text2,
18 regexp_replace(t.replaced_text2,
19 '([^[:alpha:]]+|^)' || regexp_substr(s.text1, '[[:alpha:]\'']+', 1, t.lvl + 1, 'i') || '([^[:alpha:]]+|$)',
20 '' || regexp_substr(s.text1, '[[:alpha:]\'']+', 1, t.lvl + 1, 'i') || '',
21 1, 0, 'i'),
22 t.lvl + 1
23 from search_text s, t
24 where t.id = s.id
25 and regexp_count(s.text1, '[[:alpha:]\'']+') >= t.lvl + 1
26 )
27 select t.id,
28 t.text1,
29 t.text2,
30 max(t.replaced_text2) keep (dense_rank first order by t.lvl desc) replaced_text2
31 from t
32 group by t.id, t.text1, t.text2
33 order by id;
ID TEXT1 TEXT2 REPLACED_TEXT2
---- ---------------------------------------- ---------------------------------------- ----------------------------------------
100 Inband signaling used in transmission th USER Bandwidth >inband Signaling< (TRans user bandwidth >Inband signaling< (trans
at reduces the available user bandwidth mission> mission>
from 1.544 to 1.536 Mbps.