Справочник объектов поиска и анализа

от автора

Сталкивались ли вы с кейсом, когда по заданному списку email или номеров телефонов необходимо проверить всех клиентов на совпадение с ними? Поиск через интерфейс в различных системах не всегда удобен или даже невозможен. В этой статье я расскажу, как организовать универсальное хранилище объектов различного типа под разные цели. Мы создадим единый справочник в базе данных и организуем поиск по нему. Примеры кода будут приведены на языке Oracle PL/SQL, но их легко можно адаптировать под другие СУБД.

Основная таблица для хранения объектов содержит следующие поля:

create table OBJ_LST(  iid   NUMBER not null,  cacc  VARCHAR2(2000),  ctype VARCHAR2(10),  ddate DATE default trunc(Sysdate));
  • объект хранения — строка,

  • тип объекта — это бизнес‑тип, определенный в отдельном справочнике типов (например, ИНН, email или номер банковской карты),

  • дата добавления в справочник — дает возможность вести аудит изменений и хранения историчных данных.

В справочнике типов заводятся бизнес‑типы данных с указанием их id, описания и регулярного выражения.

Рис. 1.Справочник бизнес-типов объектов

Рис. 1.Справочник бизнес‑типов объектов

Объекты удобно группировать, чтобы работать с их подмножествами. Для этого есть справочник групп (или видов). В данном примере заведены группы для организации различных проверок в банке:

Рис. 2. Группы объектов

Рис. 2. Группы объектов

А сами группировки хранятся в отдельной таблице.

Для работы с данным хранилищем необходимо решить две задачи — работу с данными и организацию поиска.

При работе с данными помимо функций добавления, редактирования и удаление записей будем автоматизировать их группировку, а также массовое заведение. С первыми операциями проблем быть не должно, там будут простые CRUD‑операции. А вот массовое заведение по списку значений, заданных одной строкой, представляет бОльший интерес. Для этого используем процедуру, на вход которой подаем строку со списком объектов, тип объекта и группу (необязательный параметр) для автоматической группировки:

parse_str(pMess => cMess, pType => 'EMAIL', pStr => 'invanov@gmail.ru; petrov@mail.ru; sidorov@inbox.ru', pCtrl => 4)

Результатом выполнения будет заполнение хранилища объектами заданного типа.

Исходный код процедуры:

PROCEDURE parse_str(pMess OUT VARCHAR2, pType IN VARCHAR2, pStr IN CLOB, pCtrl IN NUMBER)IS    cPatt VARCHAR2(254);    vStr CLOB := pStr;    CURSOR curTypes IS        SELECT CREGEXP FROM obj_types            WHERE CTYPE = pType;BEGIN    OPEN curTypes;    FETCH curTypes INTO cPatt;    CLOSE curTypes;    IF cPatt IS NULL THEN        pMess := 'Не указано регулярное выражение для типа данных '||pType; RETURN;    END IF;    dbms_output.put_line('Строка для анализа: '||vStr);    FOR rOBJ IN (SELECT SUBSTR(regexp_substr(obj, patt, 1, rownum),2) rez_obj                    FROM (SELECT vStr AS obj                    , cPatt AS patt FROM dual) dual                    CONNECT BY level <= regexp_count(obj, patt)                )    LOOP        IF rOBJ.rez_obj IS NOT NULL THEN            begin                ins_obj(rOBJ.rez_obj,pType,pCtrl);            EXCEPTION WHEN DUP_VAL_ON_INDEX THEN            END;        END IF;    END LOOP;    pMess := 'Разбор успешно завершен.';EXCEPTION WHEN OTHERS THEN  pMess := 'Непредвиденная ошибка обработки: '||SQLERRM;END parse_str;

Для организации поиска объекта по хранилищу создадим функцию, на вход которой подаем строку/объект для анализа, тип объекта (если пусто — то ищем по всем), номер группы (если пусто — то по всем) и дату загрузки данных (если пусто, то по всем):

check_str('Назначение платежа с указание номера банковской карты № 4976980039148296 договор ДГ45', 'CARD', 4, to_date('01.07.2026','dd.mm.rrrr'))

Если функция нашла совпадение исходной строки с объектом в базе, то она вернет этот самый объект.

Исходный код функции:

FUNCTION check_str(pStr IN VARCHAR2                 , pType IN VARCHAR2 DEFAULT 'ALL'                 , pCtrl IN NUMBER DEFAULT NULL                 , pDate IN DATE DEFAULT NULL                                 ) RETURN VARCHAR2ISBEGIN    FOR rOBJ IN (SELECT CACC                     FROM obj_lst a                    JOIN obj_grp_ctrl c ON c.idata_id = a.iid AND c.ictrl_id = nvl(pCtrl,c.ictrl_id)                 WHERE CTYPE = DECODE(pType ,'ALL',CTYPE, pType)                 AND DDATE >= nvl(pDate,to_date('01.01.1900','dd.mm.rrrr')))    LOOP        IF UPPER(pStr) LIKE '%'||UPPER(rOBJ.CACC)||'%' THEN            RETURN rOBJ.CACC;        END IF;    END LOOP;    RETURN NULL;END check_str;

Таким образом, мы получили удобный справочник для хранения различных объектов и инструменты для его заполнения и поиска.

ссылка на оригинал статьи https://habr.com/ru/articles/1064040/