【发布时间】:2020-01-21 00:54:56
【问题描述】:
我有一个包含单词和句子列的表格。这个想法是如果在单词列中找到单词,则用链接(包括单词本身)替换句子中的单词。下面的查询完美替换,但由于链接是从 temp.word 列构造的,因此句子中单词的大小写更改为 word 列中单词的大小写。有没有办法在句子本身中保留相同的大小写?
Create table temp(
id NUMBER,
word VARCHAR2(1000),
sentence VARCHAR2(2000)
);
insert into temp
SELECT 1,'automation testing', 'automtestingation Testing is popular kind of testing' FROM DUAL UNION ALL
SELECT 2,'testing','manual testing' FROM DUAL UNION ALL
SELECT 3,'manual testing','this is an old method of testing' FROM DUAL UNION ALL
SELECT 4,'punctuation','automation testing,manual testing,punctuation,automanual testing-testing' FROM DUAL UNION ALL
SELECT 5,'B-number analysis','B-number analysis table' FROM DUAL UNION ALL
SELECT 6,'B-number analysis table','testing B-number analysis' FROM DUAL UNION ALL
SELECT 7,'Not Matched','testing testing testing' FROM DUAL;
with words(id, word, word_length, search1, replace1, search2, replace2) as (
select id, word, length(word),
'(^|\W)' || REGEXP_REPLACE(word, '([][)(}{|^$\.*+?])', '\\\1') || '($|\W)',
'\1{'|| id ||'}\2',
'{'|| id ||'}',
'http://localhost/' || id || '/<u>' || word || '</u>'
FROM temp
)
, joined_data as (
select w.search1, w.replace1, w.search2, w.replace2,
s.rowid s_rid, s.sentence,
row_number() over(partition by s.rowid order by word_length desc) rn
from words w
join temp s
on instr(UPPER(s.sentence), UPPER(w.word)) > 0
and regexp_like(s.sentence, w.search1)
)
, unpivoted_data as (
select S_RID, SENTENCE, PHASE, SEARCH_STRING, REPLACE_STRING,
row_number() over(partition by s_rid order by phase, rn) rn,
case when row_number() over(partition by s_rid order by phase, rn)
= count(*) over(partition by s_rid)
then 1
else 0
end is_last
from joined_data
unpivot(
(search_string, replace_string)
for phase in ( (search1, replace1) as 1, (search2, replace2) as 2 ))
)
, replaced_data(S_RID, RN, is_last, SENTENCE) as (
select S_RID, RN, is_last,
regexp_replace(SENTENCE, search_string, replace_string,1,0,'i')
from unpivoted_data
where rn = 1
union all
select n.S_RID, n.RN, n.is_last,
case when n.phase = 1
then regexp_replace(o.SENTENCE, n.search_string, n.replace_string,1,0,'i')
else replace(o.SENTENCE, n.search_string, n.replace_string)
end
from unpivoted_data n
join replaced_data o
on o.s_rid = n.s_rid and n.rn = o.rn + 1
)
select s_rid, sentence from replaced_data
where is_last = 1
order by s_rid;
For example, for id = 1, the sentence is automtestingation Testing is popular kind of testing
After replacement it will be automtestingation http://localhost/2/<u>testing</u> is popular kind of http://localhost/2/<u>testing</u>.
The word Testing is replaced with testing(from the temp.word column).
预期的结果是
automtestingation http://localhost/2/<u>Testing</u> is popular kind of http://localhost/2/<u>testing</u>
【问题讨论】:
-
您使用的是什么版本的 Oracle? “作弊”并使用
WITH FUNCTION来回答这个问题可能更容易,但该功能是在 12c 中引入的。 -
我使用的是 11g :-/
-
嗨,乔恩,您有没有其他方法可以实现这一目标?目前,我想不出其他方法。非常感谢任何其他想法。
-
你能创建一个常规的 PL/SQL 函数吗?
-
是的,我可以。函数中要实现什么样的逻辑?
标签: oracle replace pattern-matching regexp-replace