我需要获取文件名的扩展名.扩展可以是任何长度(不仅仅是3),它们也可以不存在,在这种情况下我需要null返回.我知道我可以轻松编写一个PL/SQL函数来执行此操作,然后在查询中调用该函数,但我希望我能以某种方式完成所有内联.我真的不在乎解决方案有多长,我需要的是最快的解决方案.速度很重要,因为这最终会在非常大的桌子上运行.这就是我到目前为止......
/*
The same method is being used in all 5 examples.
It works for all of them except the first one.
The first one I need to return null
*/
SELECT substr(filename,instr(filename,'.',-1)+1,length(filename)-instr(filename,'.',-1))
FROM (select 'no_extension_should_return_null' filename from dual);
--returns: no_extension_should_return_null
SELECT substr(filename,instr(filename,'.',-1)+1,length(filename)-instr(filename,'.',-1))
FROM (select 'another.test.1' filename from dual);
--returns: 1
SELECT substr(filename,instr(filename,'.',-1)+1,length(filename)-instr(filename,'.',-1))
FROM (select 'another.test.doc' filename from dual);
--returns: doc
SELECT substr(filename,instr(filename,'.',-1)+1,length(filename)-instr(filename,'.',-1))
FROM (select 'another.test.docx' filename from dual);
--returns: docx
SELECT substr(filename,instr(filename,'.',-1)+1,length(filename)-instr(filename,'.',-1))
FROM (select 'another.test.stupidlong' filename from dual);
--returns: stupidlong
Run Code Online (Sandbox Code Playgroud)
那么是否有一种快速的方法可以实现内联,或者我应该在PL/SQL函数中编写它?
这就是我正在使用的......
select * from v$version;
Oracle Database 11g Enterprise Edition Release 11.2.0.2.0 - 64bit Production
PL/SQL Release 11.2.0.2.0 - Production
CORE 11.2.0.2.0 Production
TNS for 64-bit Windows: Version 11.2.0.2.0 - Production
NLSRTL Version 11.2.0.2.0 - Production
Run Code Online (Sandbox Code Playgroud)
更新 我正在将此代码移动到一个函数中,并设置一个测试来调用它一百万次以查看函数是否减慢了它,我认为它不会产生影响,因为它只是字符串操作.
更新 到目前为止感谢您的答案.我最终制作了一个PL/SQL函数来完成我需要的...
create or replace function extrip(filename varchar2) return varchar2 as
begin
if ( instr(filename,'.',-1) = 0 ) then
return null;
end if;
return substr(filename,instr(filename,'.',-1)+1,length(filename)-instr(filename,'.',-1));
end;
Run Code Online (Sandbox Code Playgroud)
然后我对一个有200万行的表进行了两次测试.当我查看两者的解释计划时,他们都是100%身份.怎么会这样?
select regexp_substr(filename, '\.[^\.]*$') ext from testTable;
select extrip(filename) ext from testTable;
Run Code Online (Sandbox Code Playgroud)
更新
我添加了order by ext两个然后重新测试,并有一个区别.正则表达式需要9秒,函数需要17秒.我想如果没有TOAD的订单,只需要重新开始第一个X数量的rec.所以@Brian McGinity是对的.我仍然需要regexp方法来不返回点"." 虽然.
Bri*_*ity 10
当你完成100%sql时它会运行得最快.
substr/instr是oracle中的本机编译函数.
如果你把它放在一个plsql函数中,由于sql和plsql之间的上下文切换,它会运行得更慢:
由于上下文切换,这种情况较慢:
select extrip( filename ) from million_row_table
Run Code Online (Sandbox Code Playgroud)
你拥有的更快.
试试这个:
select s,
substr(s, nullif( instr(s,'.', -1) +1, 1) )
from (
select 'no_extension_should_return_null' s from dual union
select 'another.test.1' from dual union
select 'another.test.doc' from dual union
select 'another.test.docx' from dual union
select 'another.test.stupidlng' from dual
)
Run Code Online (Sandbox Code Playgroud)
您需要使用正则表达式。
尝试
select regexp_substr(filename, '\.[^\.]*$')
from
(select 'no_extension_should_return_null' filename from dual);
Run Code Online (Sandbox Code Playgroud)
我没有 Oracle 数据库来测试它,但这应该非常接近。
有关详细信息,请查看有关 regexp_substr和在 Oracle 数据库中使用正则表达式的Oracle 文档。
要从文件扩展名中删除句点:
select substr(regexp_substr(filename, '\.[^\.]*$'), 2)
from
(select 'abc.def' filename from dual);
Run Code Online (Sandbox Code Playgroud)