Oracle SQL'de belirli bir karaktere kadar bir alt dize nasıl seçilir?


82

Şöyle sonuçlara sahip bir tablo sütunum olduğunu varsayalım:

ABC_blahblahblah
DEFGH_moreblahblahblah
IJKLMNOP_moremoremoremore

Söz konusu tablodan bu sütunu seçen, ancak yalnızca Alt Çizgi (_) karakterine kadar alt dizeyi döndüren bir sorgu yazabilmek istiyorum. Örneğin:

ABC
DEFGH
IJKLMNOP

SUBSTRING işlevi göreve bağlı görünmüyor çünkü bu, konuma dayalıdır ve alt çizginin konumu değişir.

TRIM işlevini düşündüm (özellikle RTRIM işlevi):

SELECT RTRIM('listofchars' FROM somecolumn) 
FROM sometable

Ancak bunu nasıl çalıştıracağımdan emin değilim, çünkü yalnızca belirli bir karakter listesini / karakter grubunu kaldırıyor gibi görünüyor ve ben gerçekten sadece Alt Çizgi karakterine giden karakterlerin peşindeyim.

Yanıtlar:


141

SUBSTR, INSTR ve NVL kombinasyonunu kullanmak (alt çizgisiz dizeler için) istediğinizi döndürecektir:

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

Sonuç:

output
------
ABC

Kullanım:

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

Referans:

Ek

Oracle10g + kullanıyorsanız, REGEXP_SUBSTR aracılığıyla normal ifadeyi kullanabilirsiniz .


Teşekkürler. Çok zarif! (REGEXP_SUBSTR hakkında bilmek de güzel.) Oracle'da Regex desteği aramayı düşünmedim bile.
Pretzel

Oracle'da işlevler (bağımsız veya bir pakette) oluşturabilir ve bunları bir seçim ifadesinde kullanabilirsiniz.
bart

9
Aradığınız alt dizeyi İÇERMEYEN değerlere karşı çalıştırılırsa başarısız olur. instrvarsa 0 döndürür INSTR('ABC/D', '_'). Sonunda, 0'dan (0-1) 'e kadar boş olan bir alt dizeniz var. İyi değil.
Marcel Stör

41

Bu, REGEXP_SUBSTR kullanılarak kolayca yapılabilir .

Lütfen kullan

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

nerede STRING_EXAMPLE sizin dizedir.

Deneyin:

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

Sorununuzu çözecektir.


1
Bir hile yaptığı için OP tarafından seçilen çözüme göre bunu yükseltiyorum. Yine de, bu çözümün @OMG Ponies'in çözümünden çok daha yavaş olduğunu belirtmekte fayda var, özellikle de koşullar altında kullanılıyorsa. Testlerim, aynı sorgunun yaklaşık 6 kat daha yavaş gerçekleştirildiğini gösterdi. Bu soru stackoverflow.com/questions/41156391/…
Ister

Testlerimde INSTRçözüm , çözümle hemen hemen aynı hızda performans gösteriyor REGEXP.
alexherm

7

İlk alt çizginin konumunu (INSTR kullanarak) ve ardından dizenin 1. karakterden (pos-1) alt çizgiye kadar olan kısmını almalısınız.

  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

Instr belgeleri

Susbtr Belgeleri


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

user1717270 tarafından yayınlanan doğru cevap

Eğer kullanırsanız INSTR, bu size o İçinde "_" içeren varsayan bir dize için pozisyon verecektir. Ya olmazsa? Cevap 0 olacaktır. Bu nedenle, dizeyi yazdırmak istediğinizde, bir NULL. Örnek: Alanı bir "host.domain" alanından kaldırmak istiyorsanız. Bazı durumlarda yalnızca kısa ada sahip olursunuz, yani "ana bilgisayar". Büyük olasılıkla "ana bilgisayar" yazdırmak istersiniz. Pekala, INSTRonunla size bir verecek NULLçünkü herhangi bir "." Bulamadı, yani 0'dan 0'a yazdıracak REGEXP_SUBSTR. Her durumda doğru cevabı alacaksınız:

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

HOST

ve

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

HOST



0

Sütundaki tüm Dizelerinizin alt çizgisi yoksa bunu unutmayın (... veya çıktı boş değer olacaksa):

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

0

Büyük dizeden herhangi bir alt dizeyi bulmak için:

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

Sonra dize bulmak için 'Ple'gelen String_valuebiz yapabiliriz:

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

Sonucu bulacaksınız: Ple


0

Dize pozisyonunun sabit olmaması durumunda, Select deyiminin altında beklenen çıktıyı alabiliriz.

Tablo Yapısı ID VARCHAR2 (100 BYTE) CLIENT VARCHAR2 (4000 BYTE)

Veri Kimliği İSTEMCİ
1001 {"clientId": "con-bjp", "clientName": "ABC", "providerId": "SBS"}
1002 {"IdType": "AccountNo", "Id": "XXXXXXXX3521", "ToPricingId": "XXXXXXXX3521", "clientId": "Test-Cust", "clientName": "MFX"}

Gereksinim - CLIENT sütununda "ClientId" dizesini arayın ve ilgili değeri döndürün. "ClientId" den: "con-bjp" -> con-bjp (Beklenen çıktı)

MÜŞTERİ, substr (substr (CLIENT, enstr (CLIENT, '"clientId": "') + uzunluk ('" clientId ":"')), 1, enstr (substr (CLIENT, enstr (CLIENT, '"clientId") seçin : "') + uzunluk ('" clientId ":" ')),' "', 1) -1) TEST_SC'den cut_str;

MÜŞTERİ cut_str ------------------------------------------------ ----------- ---------- {"clientId": "con-bjp", "clientName": "ABC", "providerId": "SBS"} con- bjp {"IdType": "AccountNo", "Id": "XXXXXXXX3521", "ToPricingId": "XXXXXXXX3521", "clientId": "Test-Cust", "clientName": "MFX"} Test-Cust

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.