案例:在字符串類型字段中 求目標子串出現的次數(在oracle 9i下測試)
1.建測試數據。建表test_tbl(含字符串類型的字段content),插入10W條記錄。
--建表
create table test_tbl (id number,content varchar2(1000));
--插入10W條測試記錄
begin
dbms_random.seed(12345678);
for i in 1 .. 100000
loop
insert into test_tbl values(i, dbms_random.string('L',dbms_random.value(10,1000)));
end loop;
commit;
end;
2.創建自定義函數一(采用循環截子串的方式實現,如果截到的子串等于目標子串則出現次數加1。)
create or replace function f1(str_pattern in varchar2,str_mother in varchar2)
return number
is
i number := 1;
cnt number := 0;
len_pattern number := length(str_pattern);
len_mother number := length(str_mother);
begin
while(i <= len_mother)
loop
if(substr(str_mother, i ,len_pattern) = str_pattern) then
cnt := cnt + 1;
i := i+ len_pattern;
else
i := i+1;
end if;
end loop;
return cnt;
end;
3.創建自定義函數二(循環使用Instr函數利用occurrence參數實現,循環一次Intr函數得到一個位置pos值,并讓occurrence加1。如果pos值不為零,表示目標子串第occurrence次在母串中存在;反之表示再也不存在了,于是退出循環。最后occurrence-1即為所得)
Intr函數說明:Instr(string, substring, position, occurrence) 其中
string:代表源字符串;
substring:代表想聰源字符串中查找的子串;
position:代表查找的開始位置,該參數可選的,默認為 1;
occurrence:代表想從源字符中查找出第幾次出現的substring,該參數也是可選的,默認為1;
返回值為:查找到的字符串的位置。
create or replace function f2(str_pattern in varchar2,str_mother in varchar2)
return number
is
pos number;
occurrence number := 1;
begin
loop
pos := instr(str_mother,str_pattern,1, occurrence);
exit when pos = 0;
occurrence := occurrence + 1;
end loop;
return occurrence - 1;
end;
3.測試效率
--用時59.223 S
select count(*) from test_tbl where f2('abc',content) > 1
--用時2.016 S
select count(*) from test_tbl where f1('a',content) > 10
--用時59.453 S
select count(*) from test_tbl where f2('a',content) > 10
--用時8.36 S
4.總結:很好的利用內置函數,科學的把內置函數放到合理的位置能很好的提高效率
5.后記
對于該案例,如果目標子串含有多個字符用f2效率較高,如果目標子串所含字符很少比如就一個字符,建議用簡便辦法:1.在母字符串中把木目標字串替換為空('')得到新字符串。2.利用 (母串長度-新串長度)/目標子串長度 得到的就是子串的出現次數。