Как выбрать подстроку в Oracle SQL до определенного символа?

82

Скажем, у меня есть столбец таблицы с такими результатами:

ABC_blahblahblah
DEFGH_moreblahblahblah
IJKLMNOP_moremoremoremore

Я хотел бы иметь возможность написать запрос, который выбирает этот столбец из указанной таблицы, но возвращает только подстроку до символа подчеркивания (_). Например:

ABC
DEFGH
IJKLMNOP

Функция SUBSTRING, похоже, не подходит для этой задачи, потому что она основана на позиции, а положение подчеркивания меняется.

Я подумал о функции TRIM (конкретно о функции RTRIM):

SELECT RTRIM('listofchars' FROM somecolumn) 
FROM sometable

Но я не уверен, как мне заставить это работать, поскольку кажется, что он удаляет только определенный список / набор символов, и я действительно только после символов, ведущих к символу подчеркивания.

Крендель
источник

Ответы:

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 .

OMG Пони
источник
Благодарю. Очень элегантный! (хорошо знать и о REGEXP_SUBSTR.) Я даже не подумал искать поддержку Regex в Oracle.
Крендель
В Oracle вы можете создавать функции (автономные или в пакете) и использовать их в операторе выбора.
Барт
9
Ошибка при выполнении со значениями, НЕ содержащими искомую подстроку. instrвозвращает 0, если у вас есть INSTR('ABC/D', '_'). В итоге у вас есть подстрока от 0 до (0-1), которая имеет значение NULL. Не хорошо.
Marcel Stör
41

Это легко сделать с помощью REGEXP_SUBSTR .

Пожалуйста, используйте

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

где STRING_EXAMPLE - ваша строка.

Пытаться:

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

Это решит вашу проблему.

user1717270
источник
1
Я поддерживаю это решение, выбранное OP, поскольку оно помогает. Тем не менее, стоит отметить, что это решение намного медленнее, чем решение @OMG Ponies, особенно если оно используется в определенных условиях. Мои тесты показали примерно в 6 раз более медленное выполнение идентичного запроса. Этот вопрос идет еще дальше по теме stackoverflow.com/questions/41156391/…
Ister
В моем тестировании INSTRрешение работает примерно так же быстро, как и REGEXPрешение.
alexherm
7

Вам нужно получить позицию первого символа подчеркивания (используя INSTR), а затем получить часть строки от 1-го символа до (pos-1), используя substr.

  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

Документация Susbtr

Раджеш Чамарти
источник
6
SELECT REGEXP_SUBSTR('STRING_EXAMPLE','[^_]+',1,1)  from dual

это правильный ответ, как написал user1717270

Если вы используете INSTR, он предоставит вам позицию для строки, которая предполагает, что она содержит "_". А если нет? Ответом будет 0. Следовательно, когда вы хотите напечатать строку, она напечатает NULL. Пример: Если вы хотите удалить домен из "host.domain". В некоторых случаях у вас будет только короткое имя, то есть «хост». Скорее всего, вы хотите вывести «хост». Что ж, с INSTRего NULLпомощью REGEXP_SUBSTRвы получите ответ, потому что он не нашел ни одного символа ".", Т.е. он будет печатать от 0 до 0. С его помощью вы получите правильный ответ во всех случаях:

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
SJOH
источник
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

Vishal Pathak
источник
0

В случае, если позиция String не зафиксирована, то с помощью оператора Select ниже мы можем получить ожидаемый результат.

ID структуры таблицы VARCHAR2 (100 BYTE) CLIENT VARCHAR2 (4000 BYTE)

Data- ID CLIENT
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 (Ожидаемый результат)

выберите КЛИЕНТ, substr (substr (CLIENT, instr (CLIENT, '"clientId": "') + length ('" clientId ":"')), 1, instr (substr (CLIENT, instr (CLIENT, '"clientId" : "') + length ('" clientId ":" ')),' "', 1) -1) cut_str из TEST_SC;

КЛИЕНТ cut_str ------------------------------------------------ ----------- ---------- {"clientId": "con-bjp", "clientName": "ABC", "providerId": "SBS"} con- bjp {"IdType": "AccountNo", "Id": "XXXXXXXX3521", "ToPricingId": "XXXXXXXX3521", "clientId": "Test-Cust", "clientName": "MFX"} Test-Cust

Амит Вашиштха
источник