Поиск определенного символа в строке - Oracle. Поиск символа в строке sql


sql - Поиск определенного символа в строке - Oracle

Это немного сложно, так как он должен быть нечувствительным к регистру (для таких вещей, как iIi или tpT). Обычно вы просто используете UPPER(), но хотите сохранить регистр остальных столбцов. Он также должен заменить МНОГО разных "неправильных" букв. И, наконец, вы не хотите, чтобы что-то вроде xxxtpt было подобрано, что сложно, если вы не можете идти пробелами (так как это может быть в начале или конце). Я не уверен, какова ваша конечная цель. Я могу думать о двух:

  • Вы просто хотите, чтобы запрос правильно отформатировал результаты.
  • Вы хотите обновить любые значения, содержащие это.

В любом случае, это самое простое решение, которое я могу придумать (хотя и исправно). Вам придется учитывать все неправильные комбинации случаев (например: tpt, tpT, tPt, tPT, Tpt, TPt). Это немного грубая сила, но из-за нехватки времени и простоты (особенно если это всего лишь несколько случаев) это будет работать:

код:

Select Trim( Replace( Replace( Replace( Replace( Replace( --note the ' ' are added so we can search for a isolated instance of --' tpt ' at the beginning or end of lines, as well as inbetween -- these space get Trim()'d at in the end of processing everything. Replace(' ' || test_t.text || ' ', ' tpt ', ' TPT ') , ' tpT ', ' TPT ') , ' tPt ', ' TPT ') --etc... , ' iii ', ' III ') --etc... , ' Iii ', ' III ') , ' IIi ', ' III ') ) as text --poor man way of creating test tables From ( Select 'tpt Broker' as text From dual UNION ALL Select 'Mark iii' as text From dual UNION ALL Select 'Davidtpt' as text From dual ) test_t

Результаты:

TPT Broker Mark III Davidtpt

Это в значительной степени бедный человек. Я уверен, что есть лучшие решения, если это долгосрочная проблема, но если ваши данные очищаются, это может сработать. Вы также можете попробовать использовать REGEXP_REPLACE или комбо из INSTR. Если я подумаю о чем-то лучше, я обновлю это сообщение.

EDIT:

О, я знал, что должен быть лучший способ. Использование REGEXP_REPLACE упрощает это. Я не смог заставить запрос "нечувствительный к регистру" работать (возможно, что-то не замечал). Такая же методология, но здесь действительно достойное решение: Select Trim( REGEXP_REPLACE( REGEXP_REPLACE( ' ' || text || ' ' , ' [tT][pP][tT] ', ' TPT ') , ' [iI][iI][iI] ', ' III ') ) as text From ( Select 'tPt Broker' as text From dual UNION ALL Select 'Mark iii' as text From dual UNION ALL Select 'Davidtpt' as text From dual ) test_t

qaru.site

sql - Запрос Oracle для поиска всех вхождений символа в строке

Расширение ответа GolezTrol позволяет использовать регулярные выражения для значительного сокращения числа рекурсивных запросов:

select instr('SSSRNNSRSSR','R', 1, level) from dual connect by level <= regexp_count('SSSRNNSRSSR', 'R')

REGEXP_COUNT() возвращает количество совпадений шаблона, в этом случае число R существует в SSSRNNSRSSR. Это ограничивает уровень рекурсии точным номером, в котором вы нуждаетесь.

INSTR() просто ищет индекс R в вашей строке. level - это глубина рекурсии, но в этом случае это также уровень th вхождения строки, поскольку мы ограничились количеством требуемых рекурсий.

Если строка, которую вы хотите выбрать, сложнее, вы можете использовать регулярные выражения ans REGEXP_INSTR() в отличие от INSTR(), но это будет медленнее (не сильно), и это необязательно, если только не требуется.

Простой критерий по запросу:

Два решения CONNECT BY указывают, что использование REGEXP_COUNT на 20% быстрее на строке этого размера.

SQL> set timing on SQL> SQL> -- CONNECT BY with REGEX SQL> declare 2 type t__num is table of number index by binary_integer; 3 t_num t__num; 4 begin 5 for i in 1 .. 100000 loop 6 select instr('SSSRNNSRSSR','R', 1, level) 7 bulk collect into t_num 8 from dual 9 connect by level <= regexp_count('SSSRNNSRSSR', 'R') 10 ; 11 end loop; 12 end; 13 / PL/SQL procedure successfully completed. Elapsed: 00:00:03.94 SQL> SQL> -- CONNECT BY with filter SQL> declare 2 type t__num is table of number index by binary_integer; 3 t_num t__num; 4 begin 5 for i in 1 .. 100000 loop 6 select pos 7 bulk collect into t_num 8 from ( select substr('SSSRNNSRSSR', level, 1) as character 9 , level as pos 10 from dual t 11 connect by level <= length('SSSRNNSRSSR') ) 12 where character = 'R' 13 ; 14 end loop; 15 end; 16 / PL/SQL procedure successfully completed. Elapsed: 00:00:04.80

Функция конвейерной таблицы работает медленнее, хотя было бы интересно посмотреть, как она выполняется над большими строками с большим количеством совпадений.

SQL> -- PIPELINED TABLE FUNCTION SQL> declare 2 type t__num is table of number index by binary_integer; 3 t_num t__num; 4 begin 5 for i in 1 .. 100000 loop 6 select * 7 bulk collect into t_num 8 from table(string_indexes('SSSRNNSRSSR','R')) 9 ; 10 end loop; 11 end; 12 / PL/SQL procedure successfully completed. Elapsed: 00:00:06.54

qaru.site

sql - найти недопустимые символы в строке

Если вам действительно нужно найти недопустимые символы в строке (а не просто найти строки, которые являются недопустимыми), возможно, этот более сложный запрос поможет. Вы не указали, в каком формате вам может понадобиться вывод, поэтому я сделал свой собственный. Я также создал несколько строк для тестирования (в частности, всегда важно проверить правильность обработки ввода NULL).

Столбец len показывает длину ввода, если он не равен 11. Длина пустой строки (null в Oracle) показана как 0. В столбцах first-nondigit упоминаются символы, начинающиеся с позиции SECOND в строке (игнорирование первый символ, для которого правила разные, и который проверяется на достоверность отдельно).

with inputs ( str ) as ( select 'N0123456789' from dual union all select '' from dual union all select '02324434323' from dual union all select 'N02345678' from dual union all select 'A2140480080' from dual union all select 'N93049c4995' from dual union all select 'N4448883333' from dual union all select 'PAR3993949Z' from dual union all select 'AN39E' from dual ) -- end of test data; query begins below this line select str, case when regexp_like(str, '^N\d{10}$') then 'valid' else 'invalid' end as classif, case when length(str) != 11 then length(str) when str is null then 0 end as len, case when substr(str, 1, 1) != 'N' then substr(str, 1, 1) end as first_char, regexp_substr(str, '[^0-9]', 2) as first_nondigit, nullif(regexp_instr( str, '[^0-9]', 2), 0) as first_nondigit_pos from inputs ;

ВЫВОД

STR CLASSIF LEN FIRST_CHAR FIRST_NONDIG FIRST_NONDIGIT_POS ----------- ------- ----- ---------- ------------ ------------------ N0123456789 valid invalid 0 02324434323 invalid 0 N02345678 invalid 9 A2140480080 invalid A N93049c4995 invalid c 7 N4448883333 valid PAR3993949Z invalid P A 2 AN39E invalid 5 A N 2 9 rows selected.

qaru.site