如何在SQL Server 2008R2中用9位随机数替换SSN?

时间:2012-12-31 19:13:35

标签: tsql sql-server-2008

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

我无法找到满足我特定需求的解决方案。似乎没什么。但如果你知道我错过了一个帖子,请告诉我。

感谢您的帮助!

5 个答案:

答案 0 :(得分:4)

这是一种方式。

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

以下我假设您的表名为,其中您的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)

答案 1 :(得分:2)

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

下一个技巧是确保它对表中的所有值都是唯一的。这很棘手,我会通过设置一个带有值的临时表,填充它,然后将它们复制过来来实现。承租人现在......

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次迭代后添加一个检查以退出循环,

答案 2 :(得分: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)

答案 3 :(得分: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

答案 4 :(得分:0)

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

       SELECT CAST(RAND(SSN)*999999999 AS INT)