Не могу поверить, что наконец-то добрался до этого. Я почти решился разделить описание последних двух функций на две статьи, но решил, что они настолько похожи на остальные, что можно обойтись одной. Подобно тому, как Профессор и Мэри Энн были не менее важны, чем другие потерпевшие кораблекрушение, эти функции тоже очень полезны, а краткость изложения тут только потому, что по принципу работы они очень похожи на все остальные. Я определенно продемонстрирую функциональность каждой функции, но не так подробно, как в предыдущих статьях.
В этой статье мы рассмотрим:
- REGEXP_INSTR — Возвращает начальную или конечную позицию соответствующей подстроки в зависимости от значения аргумента return_option.
- REGEXP_COUNT — Подсчитывает количество совпадений шаблона регулярного выражения в строке.
REGEXP_INSTR
В SQL Server нет функции INSTR, хотя PATINDEX служит достаточно близким аналогом для сравнения. PATINDEX принимает два параметра — входную строку и LIKE-выражение, позволяя найти первый символ первого вхождения этого шаблона. Например:
SELECT PATINDEX('%3%','1234567890');
Это возвращает 3. Цифра 3 явно находится в позиции 3, но с символами '%', окружающими её, может показаться, что должно быть 1. Но точно так же, как мы ищем шаблон с помощью регулярных выражений с открытым шаблоном, PATINDEX также использует "любое количество любых символов" в шаблоне поиска вместе с конкретным строковым значением, которое вы ищете, если хотите (поиск шаблона '%' вернёт 1 даже для пустой строки).
REGEXP_INSTR имеет эти (уже знакомые по серии) параметры, за исключением одного:
REGEXP_INSTR ( string_expression, pattern_expression [, start [, occurrence [, return_option [, flags [, group ] ] ] ] ] )
Параметр return_option — я опишу ниже.
Простейшая форма:
В простейшей форме вы просто передаёте строковое значение и шаблон для поиска. Этот шаблон соответствует цифре 3 (плюс любые символы до и после).
SELECT REGEXP_INSTR('1234567890','3');
Это возвращает:
----------- 3
Поскольку цифра 3 находится в третьей позиции.
Добавление параметров start и occurrence
Параметры start и occurrence работают точно так же, как в функции REGEXP_SUBSTR. Вы можете использовать один для поиска местоположения значения, а другой для поиска фактического значения с теми же начальными 4 параметрами.
Например, используя строку чисел из статьи о REGEXP_SUBSTR, я найду шаблон для первого, второго и третьего вхождений.
SELECT REGEXP_INSTR('1234567890','\d{3}',1,1) AS Loc_1, REGEXP_SUBSTR('1234567890','\d{3}',1,1) AS Value_1, REGEXP_INSTR('1234567890','\d{3}',1,2) AS Loc_2, REGEXP_SUBSTR('1234567890','\d{3}',1,2) AS Value_2, REGEXP_INSTR('1234567890','\d{3}',1,3) AS Loc_3, REGEXP_SUBSTR('1234567890','\d{3}',1,3) AS Value_3
Как видите, это позиции 1, 4 и 7, а также найденные значения:
Loc_1 Value_1 Loc_2 Value_2 Loc_3 Value_3 ------- -------- ------- ---------- ------- ---------- 1 123 4 456 7 789
Параметр return_option
Одно главное отличие REGEXP_INSTR от других рассмотренных нами функций — это параметр return_option. Он показывает позицию сразу после окончания шаблона. Это немного сбивает с толку (и числовой параметр не очень в этом помогает), но с этим значением вы можете найти начало и конец (и, вычтя 1 из значения), можете найти местоположение начала и конца совпадения с вашим шаблоном.
Возможные значения параметра return_option:
0 (по умолчанию) — вернуть начальную позицию значения
1 — вернуть первую позицию после значения
В следующем фрагменте кода я добавил значение return_option 0 или 1 для начала и конца каждой позиции:
SELECT REGEXP_INSTR('1234567890','\d{3}',1,1,0) AS Start_1, REGEXP_INSTR('1234567890','\d{3}',1,1,1) AS NextPos_1, REGEXP_SUBSTR('1234567890','\d{3}',1,1) AS Value_1, REGEXP_INSTR('1234567890','\d{3}',1,2,0) AS Start_2, REGEXP_INSTR('1234567890','\d{3}',1,2,1) AS NextPos_2, REGEXP_SUBSTR('1234567890','\d{3}',1,2) AS Value_2;
Это возвращает:
Start_1 NextPos_1 Value_1 Start_2 NextPos_2 Value_2 -------- ----------- -------- --------- ----------- -------- 1 4 123 4 7 456
Здесь я не совсем уверен в сценарии использования потому что в основном мне нужны позиции значений для использования с вызовами функций SUBSTRING/RIGHT/LEFT, но со всей мощью семейства функций REGEXP_%, большая часть работы со строками делается за нас.
Параметр group
Пропуская параметр flag, который работает так же, как в предыдущих функциях, есть параметр group. Этот параметр работает очень похоже на то, как это было в функции REGEXP_SUBST (и, как я покажу, это даст вам местоположение группы, которую вы могли получить с помощью вызова REGEXP_SUBSTR).
Вот пример вызова. Становится немного сложно следить, поскольку нельзя именовать параметры, но в следующем вызове я добавил комментарии, которые, надеюсь, помогут:
SELECT REGEXP_INSTR( --Значение для разбора: 'abc1234567890987654321', --Шаблон регулярного выражения: '(\d{1})(\d{2})', --Начальная позиция: 1, --Вхождение: 2, --Опция возврата: 0, --(означает вернуть начало) --Флаги: '', --Группа: 2 ) AS REGEXP_INSTR_2
Это возвращает:
REGEXP_INSTR_2 -------------- 8
Рассматривая значение:
Позиция: 1234567890123456789012 Значение: abc1234567890987654321
Вы можете видеть, что первая цифра 4 находится в позиции 7 (и что первый символ находится во второй группе из 3 цифр). Первая группа начинается в позиции 7 и имеет длину один символ. Поэтому вторая группа появляется в 8-й позиции. Для более подробного рассмотрения:
SELECT REGEXP_SUBSTR('abc1234567890987654321', '(\d{1})(\d{2})',1,2) as REGEXP_SUBSTR, REGEXP_SUBSTR('abc1234567890987654321', '(\d{1})(\d{2})',1,2,'',1) as REGEXP_SUBSTR_1, REGEXP_SUBSTR('abc1234567890987654321', '(\d{1})(\d{2})',1,2,'',2) as REGEXP_SUBSTR_2 SELECT REGEXP_INSTR('abc1234567890987654321', '(\d{1})(\d{2})',1,2) as REGEXP_INSTR, REGEXP_INSTR('abc1234567890987654321', '(\d{1})(\d{2})',1,2,0,'',1) as REGEXP_INSTR_1, REGEXP_INSTR('abc1234567890987654321', '(\d{1})(\d{2})',1,2,0,'',2) as REGEXP_INSTR_2
Это выводит:
REGEXP_SUBSTR REGEXP_SUBSTR_1 REGEXP_SUBSTR_2 -------------- ---------------- --------------- 456 4 56 REGEXP_INSTR REGEXP_INSTR_1 REGEXP_INSTR_2 -------------- ---------------- --------------- 7 7 8
Как видите, это очень похоже на рассмотренный ранее пример, где вы можете видеть строку и группы в вызовах REGEXP_SUBSTR и их местоположения в вызовах REGEXP_INSTR.
REGEXP_COUNT
Назначение этой функции — подсчитать количество совпадений, которые вы найдёте для шаблона в строке.
Об этой функции я более или менее собираюсь сказать более или менее: вы, вероятно, можете разобраться в ней, зная всё, что мы обсуждали ранее. Я уже рассмотрел большую часть важного об этой функции во всех других статьях серии. Но это определенно интересная функция, которую вы можете использовать, особенно при начальной подготовке для определения количества совпадений, которые вы можете найти и которые нужно обработать.
Синтаксис:
REGEXP_COUNT ( string_expression, pattern_expression [ , start [ , flags ] ] )
Эта функция имеет только самые базовые параметры с дополнительным параметром start для указания начальной позиции обработки и flags, когда они нужны. Для примера я использую ту же строку и шаблон, с которыми мы работали:
SELECT REGEXP_COUNT('abc1234567890987654321', '(\d{1})(\d{2})') as REGEXP_COUNT;
Это возвращает:
REGEXP_COUNT ------------ 6
В этом контексте это точно то же самое, что и \d{3}, как видите здесь:
SELECT REGEXP_COUNT('abc1234567890987654321', '\d{3}') as REGEXP_COUNT;
Мы можем увидеть это двумя способами: либо просто подсчитав их:
111222333444555666 abc1234567890987654321
Или используя REGEXP_MATCHES и видя, сколько строк она выводит:
SELECT match_id, start_position, end_position, match_value FROM REGEXP_MATCHES('abc1234567890987654321','\d{3}') AS MATCHES;
Вы можете видеть символы в различных совпадениях:
match_id start_position end_position match_value ---------- -------------- ------------ ------------ 1 4 6 123 2 7 9 456 3 10 12 789 4 13 15 098 5 16 18 765 6 19 21 432
Что даёт 6 строк, по 1 для каждого совпадения, что вы видели в примере с REGEXP_COUNT.
REGEXP_COUNT — не та функция, которую я собираюсь часто использовать, но это ещё один полезный инструмент в арсенале, когда вы хотите узнать, сколько совпадений может быть в группе текста.
Комментариев нет:
Отправить комментарий