Vertica 中 Id_number 上的随机数字数据屏蔽

Random Digit Data Masking on Id_number in Vertica

我需要在第 6 位和第 12 位之间随机屏蔽 id_number 的 4 位数字。

示例: 555444888777 --> 55544x8x8xx7

我写了下面的代码,但它是每 2 位随机的。在 Vertica 中,给定 间隔 需要多少位数来屏蔽 是否有任何随机屏蔽的解决方案?

SELECT OVERLAYB(OVERLAYB(OVERLAYB(OVERLAYB('555444888777', 'x', 5+RANDOMINT(2)),'x', 7+RANDOMINT(2)),'x', 9+RANDOMINT(2)),'x',11+RANDOMINT(2));

这有点疯狂,但似乎有效:

with my_range as (
             select  6 as n
   union all select  7 as n
   union all select  8 as n
   union all select  9 as n
   union all select 10 as n
   union all select 11 as n
   union all select 12 as n),
random_positions as (
   select n
     from my_range
    order by random()
    limit 4),
quartiles as (
   select n,
          ntile(4) over(order by n) as quartile
     from random_positions),
sorted_positions as (
   select max(case when quartile = 1 then n end) as random1,
          max(case when quartile = 2 then n end) as random2,
          max(case when quartile = 3 then n end) as random3,
          max(case when quartile = 4 then n end) as random4
     from quartiles)
select '555444888777' as string_original,
       overlay(
         overlay(
            overlay(
               overlay('555444888777' placing 'x' from random1)
               placing 'x' from random2)
            placing 'x' from random3)
         placing 'x' from random4)
       as string_masked
  from sorted_positions;

执行示例:

$ vsql -f tmp.sql
 string_original | string_masked
-----------------+---------------
 555444888777    | 55544xx8xx77
(1 row)


$ vsql -f tmp.sql
 string_original | string_masked
-----------------+---------------
 555444888777    | 55544xx8x7x7
(1 row)


$ vsql -f tmp.sql
 string_original | string_masked
-----------------+---------------
 555444888777    | 55544x8x8x7x
(1 row)

解释:

  • my_range 用 6 到 12 的数字构建一个记录集
  • random_positions 随机排序记录集,只返回 4 个位置
  • quartiles 将四分位数分配给每个随机位置,因此 sorted_positions 可以将结果转换为单个记录
  • 最后,最后一个 select 在四个随机位置应用了四次 OVERLAY function

如果你真的想用 'x' 随机替换一个数字,随机地,位置 5、7、9 和 11 之后的第一个或第二个数字,就像你编码的那样,然后创建一个函数作为我做到了,所以您不需要每次都对嵌套的 OVERLAYB() 调用重新编码。

如果您想要更多差异,也可以用 RANDOMINT() 调用替换 5、7、9 和 11。

但是,如果您想改变替换次数(从 4 次到其他次数),您将不得不为不同的替换次数重新编写函数。或者经历在 C++、Java、R 或 Python.

中编写 UDx(用户定义的扩展)的麻烦

检查 Vertica 文档;从这里开始: https://www.vertica.com/docs/10.0.x/HTML/Content/Authoring/SQLReferenceManual/Statements/CREATEFUNCTIONUDF.htm?zoom_highlight=create%20function

话虽如此,这里是具有相同功能的函数及其测试:

CREATE OR REPLACE FUNCTION maskrand( 
  s VARCHAR(256)
) 
RETURN VARCHAR(256) 
AS 
BEGIN
  RETURN (
    OVERLAYB(
      OVERLAYB(
        OVERLAYB(
          OVERLAYB(
            s
          , 'x'
          , 5+RANDOMINT(2)
          )
          ,'x'
        , 7+RANDOMINT(2)
        )
        ,'x'
      , 9+RANDOMINT(2)
      )
      ,'x'
    , 11+RANDOMINT(2)
    )
  );
END;

-- test ...
WITH indata(s) AS (
          SELECT '555444888777'
UNION ALL SELECT '666333444888'
) 
SELECT
  s, maskrand(s) AS masked
FROM indata;
-- out       s       |    masked    
-- out --------------+--------------
-- out  555444888777 | 5554x48x8xx7
-- out  666333444888 | 6663x3x4x88x