2

为了满足安全要求,在将所述数据库提供给开发人员之前,我需要找到一种方法将SSN替换为唯一的随机 9 位数字。SSN 位于数据库表的列中。所述表中可能有数十万行。该数字不需要连字符。我是 SQL 和一般编程的初学者。

我一直无法找到满足我特定需求的解决方案。似乎没有什么是对的。但是,如果您知道我错过了一个线程,请告诉我。

谢谢你的帮助!

4

5 回答 5

8

这是一种方法。

我假设您已经备份了真实数据,因为此更新不可逆。

下面我假设您的表名是Person,您的 ssn 列名为SSN

UPDATE Person SET 
SSN = CAST(LEFT(CAST(ABS(CAST(CAST(NEWID() as BINARY(10)) as int)) as varchar(max)) + '00000000',9) as int)
于 2012-12-31T19:39:15.973 回答
2

如果它们不必是随机的,您可以将它们替换为升序数值。否则,您将不得不生成一个随机数。您可能已经发现,RAND 函数只会为每个查询语句(选择、更新等)生成一个值;解决方法是 newid() 函数,该函数将为查询生成的每一行生成一个 GUID(运行SELECT newid() from MyTable以查看其工作原理)。将其包装在 checksum() 中以生成整数;模数乘以 1,000,00,000 以获得 SSN 范围内的值(0 到 999,999,999);并且,假设您将其存储为 char(9) 前缀,并带有前导零。

下一个技巧是确保它对于表中的所有值都是唯一的。这变得很棘手,我会通过设置一个带有值的临时表,填充它,然后将它们复制过来来做到这一点。现在承租人……</p>

DECLARE @DummySSN as table
 (
   PrimaryKey  int      not null
  ,NewSSN      char(9)  not null
 )


--  Load initial values
INSERT @DummySSN 
 select
   UserId
  ,right('000000000' + cast(abs(checksum(newid()))%1000000000 as varchar(9)), 9)
 from Users

--  Check for dups
select NewSSN from @DummySSN group by NewSSN having count(*) > 1

--  Loop until values are unique
IF exists (SELECT 1 from @DummySSN group by NewSSN having count(*) > 1)
    UPDATE @DummySSN
     set NewSSN = right('000000000' + cast(abs(checksum(newid()))%1000000000 as varchar(9)), 9)
     where NewSSN in (select NewSSN from @DummySSN group by NewSSN having count(*) > 1)

--  Check for dups
select NewSSN from @DummySSN group by NewSSN having count(*) > 1

这适用于我的一张小桌子,它应该适用于一张大桌子。我没有看到这会变成无限循环,但即便如此,您可能想要添加一个检查以在 10 次迭代后退出循环,

于 2012-12-31T19:42:10.623 回答
0

我已经进行了几百万次测试,它似乎生成了随机 (URN) 9 位数字(没有前导零)。我想不出更有效的方法来做到这一点。

SELECT CAST(FLOOR(RAND(CHECKSUM(NEWID())) * 900000000 ) + 100000000 AS BIGINT)

使用的测试;

;WITH Fn(N) AS
(
    SELECT CAST(FLOOR(RAND(CHECKSUM(NEWID())) * 900000000 ) + 100000000 AS BIGINT)
    UNION ALL
    SELECT CAST(FLOOR(RAND(CHECKSUM(NEWID())) * 900000000 ) + 100000000 AS BIGINT)
    FROM Fn
)
,Tester AS
(
    SELECT TOP 5000000 *
    FROM Fn
)
SELECT   LEN(MIN(N))
        ,LEN(MAX(N)) 
        ,MIN(N)
        ,MAX(N)
FROM Tester
OPTION (MAXRECURSION 0)
于 2012-12-31T20:03:04.520 回答
0

不是那么快,但最简单...我添加了一些点...

DECLARE @tr NVARCHAR(40)
SET @tr = CAST(ROUND((888*RAND()+111),0) AS CHAR(3)) + '.' + 
    CAST(ROUND((8888*RAND()+1111),0) AS CHAR(4)) + '.' + CAST(ROUND((8888*RAND()+1111),0) AS
    CHAR(4)) + '.' + CAST(ROUND((88*RAND()+11),0) AS CHAR(2))
PRINT @tr
于 2014-06-16T13:28:04.407 回答
0

如果要求对数据库进行模糊处理,那么这将为任何表中的每个不同 SSN 返回相同的唯一值,从而在输出中保留参照完整性,而无需进行查找和翻译。

       SELECT CAST(RAND(SSN)*999999999 AS INT)
于 2016-08-31T14:38:25.900 回答