为了满足安全要求,在将所述数据库提供给开发人员之前,我需要找到一种方法将SSN替换为唯一的随机 9 位数字。SSN 位于数据库表的列中。所述表中可能有数十万行。该数字不需要连字符。我是 SQL 和一般编程的初学者。
我一直无法找到满足我特定需求的解决方案。似乎没有什么是对的。但是,如果您知道我错过了一个线程,请告诉我。
谢谢你的帮助!
为了满足安全要求,在将所述数据库提供给开发人员之前,我需要找到一种方法将SSN替换为唯一的随机 9 位数字。SSN 位于数据库表的列中。所述表中可能有数十万行。该数字不需要连字符。我是 SQL 和一般编程的初学者。
我一直无法找到满足我特定需求的解决方案。似乎没有什么是对的。但是,如果您知道我错过了一个线程,请告诉我。
谢谢你的帮助!
这是一种方法。
我假设您已经备份了真实数据,因为此更新不可逆。
下面我假设您的表名是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)
如果它们不必是随机的,您可以将它们替换为升序数值。否则,您将不得不生成一个随机数。您可能已经发现,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 次迭代后退出循环,
我已经进行了几百万次测试,它似乎生成了随机 (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)
不是那么快,但最简单...我添加了一些点...
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
如果要求对数据库进行模糊处理,那么这将为任何表中的每个不同 SSN 返回相同的唯一值,从而在输出中保留参照完整性,而无需进行查找和翻译。
SELECT CAST(RAND(SSN)*999999999 AS INT)