2012-12-31 104 views
2

爲了滿足安全性要求,我需要找到一種方法,在向開發人員提供數據庫之前,用唯一的隨機9位數字代替SSN。 SSN位於數據庫表的一列中。所述表格中可能有成千上萬的行。數字不需要連字符。我是一個初學SQL和一般編程的人。如何用SQL Server 2008R2中的9位隨機數替換SSN?

我一直無法爲我的特定需求找到解決方案。沒有什麼似乎很正確。但是,如果您知道我錯過的線索,請告訴我。

感謝您的幫助!

+0

,請告訴我們你的表結構(相關字段名稱和數據類型) – Tahbaza

+0

是期望,開發人員將能夠解密的隨機數回到正確的SSN?或者,隨機數字是唯一的ID來標識用戶? – MadHenchbot

+0

在這種情況下,不需要擁有SSN - 它是唯一的ID。將db提供給開發人員是爲了測試/調試目的,因此數據庫必須運行,但除非必要,否則必須編輯SSN(可能還有其他PII)。 – user1901945

回答

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) 
+0

工作很好。我希望結果能夠滿足要求,但它看起來不錯並且非常容易。謝謝。 – user1901945

2

如果它們不必是隨機的,那麼可以用升序數值替換它們。否則,你必須生成一個隨機數。正如您可能已經發現的那樣,RAND函數只會爲每個查詢語句(選擇,更新等)生成一個值;解決此問題的方法是newid()函數,該函數將爲查詢生成的每行生成GUID(運行SELECT newid() from MyTable以查看其工作原理)。將其包裝在校驗和()中以生成一個整數;通過1,000,000,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迭代,

+0

這裏假定SSN是表中唯一的一列。重複(兩行一個人)需要額外的處理。 –

+1

'RAND'函數*可以*生成每行不同的值,假設你給它種子'SELECT RAND(num)AS orly FROM(SELECT 1 UNION ALL SELECT 500000)D(num);' – billinkc

+1

很高興知道。如果源表中有唯一的代理鍵(如SSN),可以在這裏工作。安全純粹主義者可能會認爲這是一個可能的違規行爲,因爲您可能會從生成的值中反向設計原始值。 –

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) 
+0

對不起,我意識到這個號碼需要獨一無二。 – MarkD

+0

SO上沒有「太遲」。如果你能找出一個確保唯一性的好方法 - 我的一點點問題 - 修改你的答案! –

+0

我認爲我的建議與您選擇的答案一樣獨特(只是速度的兩倍) – MarkD

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 
0

如果要求混淆一個數據庫,那麼這將返回相同的獨特價值爲每個不同的SSN在任何表中保留輸出中的參照完整性,而不必查找和翻譯。

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