what would be the best way to do a word match search in PL/SQL?
E.g. for the string "BROUGHTONS OF CHELTENHAM LIMITED"
"BROUGHTONS LIMITED" is a match
"OF LIMITED" is a match
"CHELTENHAM BROUGHTONS" is a match
"BROUG" is a non-match
这是一种相当粗略的方法,但应该按照您的要求进行。正如 Xophmeister 所指出的,您可能需要对每个字符串进行标记,然后搜索这些标记(因为您想要乱序匹配,所以执行简单的“like %tokenA%tokenB%tokenC%”是行不通的)。
此外,这甚至没有涉及到语音、soundex 等所有问题。但同样,不是你问的。这也不会涉及性能或扩展问题,并且可能仅适用于一小组数据。
所以,首先我们需要一个拆分函数:
create or replace
function fn_split(i_string in varchar2, i_delimiter in varchar2 default ',', b_dedup_tokens in number default 0)
return sys.dbms_debug_vc2coll
as
l_tab sys.dbms_debug_vc2coll;
begin
select regexp_substr(i_string,'[^' || i_delimiter || ']+', 1, level)
bulk collect into l_tab
from dual
connect by regexp_substr(i_string, '[^' || i_delimiter || ']+', 1, level) is not null
order by level;
if (b_dedup_tokens > 0) then
return l_tab multiset union distinct l_tab;
end if;
return l_tab;
end;
现在我们可以使用它来检查特定标记的字符串。在这里,我从一组数据样本中搜索 3 个令牌(John Q Public)
with test_data as (
select 1 as id, 'John Q Public' as full_name from dual
union
select 2 as id, 'John John Smith' as full_name from dual
union
select 3 as id,'Sally Smith' from dual
union
select 4 as id, 'Mr John B B Q Public' from dual
union
select 5 as id, 'A Public John' from dual
)
select d.id, d.full_name, count(1) as hits
from test_data d, table(fn_split(full_name, ' ', 1))
-- should have at least 1 of these tokens
where column_value in ('John', 'Q', 'Public')
group by d.id, d.full_name
-- can also restrict results to those with at least x token hits
having count(1) >= 2
-- most hits at top of results
order by count(1) desc, id asc
输出:
"ID" "FULL_NAME" "HITS"
1 "John Q Public" 3
4 "Mr John B B Q Public" 3
5 "A Public John" 2
您还可以添加“upper”以使大小写不敏感等。
使用 Oracle Text 索引。这将允许您发出强大的 CONTAINS 查询。
http://docs.oracle.com/cd/B28359_01/text.111/b28303/quicktour.htm