继续这个问题。
在工作中,我必须使用各种数据源,并且经常遇到质量较差的数据(手动输入系统)并且存储在不符合 3NF(3x 范式)规则的表中。那些。通常多个实体存储在一个单元格中。
例如:
email
-------------------------------------
mail1@mail.com, mail2@domain.com mail3@gmail.com
或者
phone
----------------------------------------------------
0172-1234/567, +49123456789 and 089 / 123-4567
我的团队面临的任务是在不更改数据模型的情况下对这些数据进行梳理和规范化,并以以下形式获取相同的数据:
email
-------------------------------------
mail1@mail.com; mail2@domain.com; mail3@gmail.com
和
phone
----------------------------------------------------
01721234567; 0049123456789; 0891234567
标准化个人电子邮件、电话等的功能。已经实现和测试要对此类数据进行规范化,首先需要以垂直形式(即 done UNPIVOT)解析和获取这些类似 CSV 的字符串,然后应用规范化函数,最后将已经规范化的值打包回 CSV 字符串相同的分隔符 ( '; ')。
在这个答案中,受人尊敬的0xdb展示了如何有效地解析此类数据并生成UNPIVOT. 根据答案中的函数,我编写了以下通用函数,它应该能够使用各种规范化函数对电话号码、WEB 地址和电子邮件进行规范化。
结果就是这个怪物:
create or replace function normalize_csv_values (
str varchar2,
typ varchar2 := 'phone',
target_sep char := '; '
) return varchar2
as
pattern varchar2(64) := '([^[:space:]].*?)((\s*[,;]\s*)|($))';
tokens varchartab := varchartab ();
s varchar2(96);
c int := 0;
l_res varchar2(1024);
begin
case
when lower(trim(typ)) in ('phone', 'fax')
then pattern := '([^[:space:]].*?)((' || '\s*(,|;|oder|o\.|or|und|and)\s*' || ')|($))';
when lower(trim(typ)) in ('url', 'web', 'link')
then pattern := '([^[:space:]].*?)((' || '[,;]' || ')|($))';
when lower(trim(typ)) in ('email')
then pattern := '([^[:space:]].*?)((' || '[[:space:],;/]' || ')|($))';
end case;
<<split>> loop c := c + 1;
s := regexp_substr (str, pattern, 1, c, null, 1);
exit split when s is null;
if lower(typ) in ('phone', 'fax') then
s := normalize_phone(s, 6, 17, '\s*\W?(,|;|oder|o.|und|or)\W?\s*');
elsif lower(typ) in ('url', 'web', 'link') then
s := normalize_url(s, '^(w{3,4}\.)');
elsif lower(typ) in ('email') then
s := normalize_email(s, '[:space:],;/');
end if;
tokens.extend;
tokens(tokens.last) := s;
end loop;
-- pack parsed CSV values back to CSV form, using specified [target_sep]
select listagg(column_value, target_sep) within group (order by rownum)
into l_res
from table(tokens);
return l_res;
end;
/
问题:
SRP (Single Responsibility Principle)你能告诉我如何以原则和的方式分解这个函数DRY (Don't Repeat Yourself)吗?
也许您可以以某种方式编写通用 RegEx 并制作一个包装函数来调用必要的规范化函数?
实施建议。
将所有函数中的正则表达式模式删除到单独的表中:
然后一个工作查询将如下所示(在db<>fiddle上):
为每个规范创建一个基本自定义类型。数据类型其继承类型:
类型实现示例:
这就是包中包含函数的解决方案的外观。
来自此答案的数据的最终请求将如下所示:
包实现(在db<>fiddle上):
到目前为止,我已经完成了分解,取出了获取 RegEx 并将各种实体规范化为单独函数的逻辑。