Сталкивались ли вы с кейсом, когда по заданному списку 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, описания и регулярного выражения.
Объекты удобно группировать, чтобы работать с их подмножествами. Для этого есть справочник групп (или видов). В данном примере заведены группы для организации различных проверок в банке:
А сами группировки хранятся в отдельной таблице.
Для работы с данным хранилищем необходимо решить две задачи — работу с данными и организацию поиска.
При работе с данными помимо функций добавления, редактирования и удаление записей будем автоматизировать их группировку, а также массовое заведение. С первыми операциями проблем быть не должно, там будут простые 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/