【问题标题】:Regex for SSN in oracle columnoracle 列中 SSN 的正则表达式
【发布时间】:2018-10-04 14:11:47
【问题描述】:

我正在尝试在我的 oracle 查询中隐藏 SSN 详细信息。

使用以下查询来识别 SSN 格式并将其替换为给定格式。

  1. dddddddddd
  2. ddd-dd-dddd

选择 regexp_replace('123-45-6789', '(^|\D+?)(\d{3}-\d{2}-|\d{5})(\d{4})($|\D+?)', '\1*** **\3\4') 输出 来自双重

如果我运行此查询,我将得到以下输出。

*****6789

同样,我也想解析以下格式。

dd-dddddddd

或者如果连字符可以在任何地方可能会更好,但它应该只读取 9 位数字。

由于我对 RegEx 不太熟悉,有人可以帮我构建满足此要求的 regex 吗?

【问题讨论】:

  • 那么,你只想屏蔽区号和组号?
  • 是的,我想屏蔽区号和组号。我只想显示最后 4 位数字。
  • 如果连字符在最后 4 位之间怎么办?
  • 现在,我只需添加“dd-dddddd”以及“ddd-dd-dddd”和“ddddddddd”即可。

标签: regex oracle


【解决方案1】:

如果您想在忽略破折号的情况下解析 SSN,最好的方法可能是在尝试应用正则表达式之前替换任何破折号(假设这些是您需要担心的唯一非数字):

REPLACE(myssn, '-', '')

然后您可以应用正则表达式(尽管可能有更有效的方法;Oracle 中的正则表达式非常昂贵):

SELECT REGEXP_REPLACE( REPLACE(myssn, '-', ''), '^.*\(d{4})$', '*****\1' )
  FROM mytable;

我个人可能会尝试以下方法,并完全避免使用正则表达式:

SELECT '*****' || SUBSTR( REPLACE(myssn, '-', ''), -4, 4 )
  FROM mytable;

希望这会有所帮助。

【讨论】:

  • OP 的正则表达式以($|\D+?) 结尾,因此您不能依赖字符串末尾的 4 位 SSN。
  • 非常简单!好点子!谢谢@David Faber
  • @MT0 我假设这些字符都会在对REPLACE() 的调用中被替换。如果还有其他非数字,则可以改用REGEXP_REPLACE(myssn, '\D+', '')
【解决方案2】:

如果您想利用 Oracle 数据库提供的现有功能,这是一个机会。

Oracle 编校功能允许在数据库中设置编校策略,这样当非特权用户查询数据时,他们只能看到他们应该能够执行的操作,这可能是空的、随机数据或部分编校的数据。

其中一项功能是一些内置的社会安全号码政策。

如果您当前的安装可以使用此功能,请检查一下,因为它可以为您在应用程序和报告层中节省大量工作。

以下是 SS# 的内置策略:

https://docs.oracle.com/cloud/latest/db121/ASOAG/redaction_config.htm#ASOAG608

Example 5-7 Partially Redacted Character Values

BEGIN
 DBMS_REDACT.ADD_POLICY(
   object_schema       => 'mavis', 
   object_name         => 'cust_info', 
   column_name         => 'ssn',
   policy_name         => 'redact_cust_ssns3', 
   function_type       => DBMS_REDACT.PARTIAL,
   function_parameters => DBMS_REDACT.REDACT_US_SSN_F5,
   expression          => '1=1',
   policy_description  => 'Partially redacts 1st 5 digits in SS numbers',
   column_description  => 'ssn contains Social Security numbers');
END;
/
Query and redacted result:

SELECT ssn FROM mavis.cust_info;

SSN
-------
XXX-XX-4320
XXX-XX-4323
XXX-XX-4325
XXX-XX-4329

【讨论】:

    【解决方案3】:

    这将捕获组中的前 5 个数字,并完全忽略任何破折号

    -*(\d-*){5}((\d-*){4})
    

    示例

    • 在:select regexp_replace('123-45-6789', '-*(\d-*){5}((\d-*){4})', '*****\2')

      • 输出:*****6789
    • 在:select regexp_replace('12-3456789', '-*(\d-*){5}((\d-*){4})', '*****\2')

      • 输出:*****6789
    • 在:select regexp_replace('---12-3--4567-89', '-*(\d-*){5}((\d-*){4})', '*****\2')

      • 输出:*****67-89

    【讨论】:

    • Oracle 不支持非捕获组(因此您的正则表达式会引发异常),您需要从表中进行选择。
    • 尝试使用非捕获组不会引发异常,但不会按预期工作。
    • @MT0 感谢您的提示,我已经删除了非捕获组。
    【解决方案4】:

    在您的正则表达式/新要求的行之间阅读,您似乎可以拥有:

    • 字符串开头的零个或多个非数字字符
    • 与以下格式匹配的 SSN:
      • ddddddddd
      • ddd-dd-dddd
      • dd-ddddddd
    • 字符串末尾有零个或多个非数字字符

    你可以使用正则表达式:

    • ^\D*\d{2}(\d{3})(\d{4})\D*$
    • ^\D*\d{2}(\d-\d\d-)(\d{4})\D*$
    • ^\D*\d{2}(-\d{3})(\d{4})\D*$

    分别匹配这 3 个模式,并且(因为唯一的区别是第一个捕获组)您可以将它们组合成一个表达式:

    ^\D*\d{2}(-?\d{3}|\d-\d\d-)(\d{4})\D*$
    

    所以你的查询是:

    SELECT REGEXP_REPLACE(
             'TEST12-3456789TEST',
             '*****\2'
           )
    FROM   DUAL
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-12-15
      • 1970-01-01
      • 2015-04-19
      相关资源
      最近更新 更多