如何在Oracle SQL中选择一个不超过特定字符的子字符串?


82

说我有一个表列,其结果如下:

ABC_blahblahblah
DEFGH_moreblahblahblah
IJKLMNOP_moremoremoremore

我希望能够编写一个查询,该查询从所述表中选择此列,但仅将子字符串返回到下划线(_)字符。例如:

ABC
DEFGH
IJKLMNOP

SUBSTRING函数似乎不适合该任务,因为它基于位置并且下划线的位置不同。

我想到了TRIM函数(特别是RTRIM函数):

SELECT RTRIM('listofchars' FROM somecolumn) 
FROM sometable

但是我不确定如何使它起作用,因为它似乎只删除了某些列表/字符集,而实际上我只是在导致下划线字符的字符之后。

Answers:


141

结合使用SUBSTR,INSTR和NVL(对于不带下划线的字符串)将返回您想要的内容:

SELECT NVL(SUBSTR('ABC_blah', 0, INSTR('ABC_blah', '_')-1), 'ABC_blah') AS output
  FROM DUAL

结果:

output
------
ABC

使用:

SELECT NVL(SUBSTR(t.column, 0, INSTR(t.column, '_')-1), t.column) AS output
  FROM YOUR_TABLE t

参考:

附录

如果使用Oracle10g +,则可以通过REGEXP_SUBSTR使用正则表达式。


谢谢。十分优雅!(也非常了解REGEXP_SUBSTR。)我什至没有想到要在Oracle中寻求Regex支持。
椒盐脆饼2010年

在Oracle中,您可以创建函数(独立的或在程序包中)并在select语句中使用它们。
巴特2010年

9
如果针对不包含您要查找的子字符串的值运行,则会失败。instr如果有,则返回0 INSTR('ABC/D', '_')。最后,您有一个从0到(0-1)的子字符串,该子字符串为null。不好。
MarcelStör2012年

39

可以使用REGEXP_SUBSTR轻松完成。

请用

REGEXP_SUBSTR('STRING_EXAMPLE','[^_]+',1,1) 

其中STRING_EXAMPLE是您的字符串。

尝试:

SELECT 
REGEXP_SUBSTR('STRING_EXAMPLE','[^_]+',1,1) 
from dual

它将解决您的问题。


1
我赞成OP选择的解决方案,因为它可以解决问题。但是,值得注意的是,此解决方案比@OMG Ponies的解决方案慢得多,尤其是在有条件的地方使用时。我的测试显示,相同查询的执行速度大约慢6倍。这个问题在主题stackoverflow.com/questions/41156391/…
Ister

在我的测试中,该INSTR解决方案的性能与该解决方案几乎一样快REGEXP
alexherm

7

您需要获取第一个下划线的位置(使用INSTR),然后使用substr获取从第一个字符到(pos-1)的字符串部分。

  1  select 'ABC_blahblahblah' test_string,
  2         instr('ABC_blahblahblah','_',1,1) position_underscore,
  3         substr('ABC_blahblahblah',1,instr('ABC_blahblahblah','_',1,1)-1) result
  4*   from dual
SQL> /

TEST_STRING      POSITION_UNDERSCORE RES
---------------- ------------------  ---
ABC_blahblahblah                  4  ABC

说明书

Susbtr文档


6
SELECT REGEXP_SUBSTR('STRING_EXAMPLE','[^_]+',1,1)  from dual

是正确的答案,如由user1717270发表

如果使用INSTR,它将为您提供一个字符串的位置,该字符串假定其中包含“ _”。如果没有,该怎么办?答案是0。因此,当您要打印字符串时,它将打印一个NULL。示例:如果要从“ host.domain”中删除域。在某些情况下,您只会使用简称,即“主机”。您最有可能希望打印“主机”。好吧,INSTR它会给你一个NULL发现一个“。”,因为它找不到任何“。”,即它将打印为0到0。REGEXP_SUBSTR在所有情况下,有了正确的答案:

SELECT REGEXP_SUBSTR('HOST.DOMAIN','[^.]+',1,1)  from dual;

主办

SELECT REGEXP_SUBSTR('HOST','[^.]+',1,1)  from dual;

主办



0

如果您在该列中的所有字符串都没有下划线(...,否则将输出空值),请记住以下几点:

SELECT COALESCE
(SUBSTR("STRING_COLUMN" , 0, INSTR("STRING_COLUMN", '_')-1), 
"STRING_COLUMN") 
AS OUTPUT FROM DUAL

0

要从大字符串中查找任何子字符串:

string_value:=('This is String,Please search string 'Ple');

然后从中查找字符串'Ple'String_value我们可以这样做:

select substr(string_value,instr(string_value,'Ple'),length('Ple')) from dual;

您会找到结果: Ple


0

如果String位置不固定,则通过在Select语句下面可以得到预期的输出。

表结构ID VARCHAR2(100 BYTE)CLIENT VARCHAR2(4000 BYTE)

数据ID客户
1001 {“ clientId”:“ con-bjp”,“ clientName”:“ ABC”,“ providerId”:“ SBS”}
1002 {“ IdType”:“ AccountNo”,“ Id”:“ XXXXXXXX3521”, “ ToPricingId”:“ XXXXXXXX3521”,“ clientId”:“ Test-Cust”,“ clientName”:“ MFX”}

要求-在“客户”列中搜索“ ClientId”字符串,并返回相应的值。像From“ clientId”:“ con-bjp”-> con-bjp(预期输出)

选择CLIENT,substr(substr(CLIENT,instr(CLIENT,'“ clientId”:“')+ length('” clientId“:”')),1,instr(substr(CLIENT,instr(CLIENT,'“ clientId” :“”)+ length('“ clientId”:“')),'”',1)-1)TEST_SC中的cut_str;

客户端cut_str ------------------------------------------------ ----------- ---------- {“ clientId”:“ con-bjp”,“ clientName”:“ ABC”,“ providerId”:“ SBS”} con- bjp {“ IdType”:“ AccountNo”,“ Id”:“ XXXXXXXX3521”,“ ToPricingId”:“ XXXXXXXX3521”,“ clientId”:“ Test-Cust”,“ clientName”:“ MFX”} Test-Cust

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.