2010-07-26 79 views
4

我想創建一個在表格中唯一但不增量的PIN,以使人們難以猜測。 理想情況下,我希望能夠在SQL Server中創建這個,但如果需要,我可以通過ASP.Net來完成。爲表格的每條記錄創建一個唯一的標識(PIN)

編輯

很抱歉,如果我沒說清楚:我不是在尋找一個GUID所有我需要的是該表的唯一ID;我只是不希望它是增量式的。

+1

有多少位數?數字或字母數字?當然,所有與安全通信初始PIN碼有關的問題。 – 2010-07-26 16:38:14

+0

個人識別號碼...號碼? RSlaughter 2010-07-26 16:50:29

+0

理想情況下儘可能短 - 可以是以太數字或字母數字。 – Josh 2010-07-26 17:10:42

回答

4

uniqueidentifier列添加到您的表中,默認值爲NEWID()。這將確保每列獲得一個新的唯一標識符,這不是增量式的。

CREATE TABLE MyTable (
    ... 
    PIN uniqueidentifier NOT NULL DEFAULT newid() 
    ... 
) 

uniqueidentifier保證是唯一的,不僅適用於此表,而且適用於所有表格。

如果這是你的應用程序太大,你可以得到你從這個數字更小的PIN碼,你可以做到這一點,如:

SELECT RIGHT(REPLACE((SELECT PIN from MyTable WHERE UserID=...), '-', ''), 4/*PinLength*/) 

注意,返回小PIN碼不能保證所有用戶的獨特,但可能更易於管理,具體取決於您的應用程序。

編輯:如果你想要一個小的PIN碼,保證唯一性,棘手的部分是,你需要知道至少最大的用戶數量,以便選擇適當的大小的引腳。隨着用戶數量的增加,PIN衝突的可能性增加。這與Coupon Collector's問題類似,並且接近nlogn複雜度,這會導致非常慢的插入(插入時間與現有元素的數量成比例,因此插入M個項目然後變爲O(N^2))。避免這種情況最簡單的方法是使用大的唯一ID,並且只選擇其中一部分用於PIN,假設您可以放棄PIN值的唯一性。

EDIT2:

如果你有這樣的

CREATE TABLE YourTable (
    [id] [int] IDENTITY(1,1) NOT NULL, 
    [pin] AS (CONVERT(varchar(9),id,0)+RIGHT(pinseed,3)) PERSISTED, 
    [pinseed] [uniqueidentifier] NOT NULL 
) 

此表定義將創建從pinseed一個唯一的ID和行ID的pin。 (RAND不起作用 - 因爲SQL服務器將使用相同的值來初始化多行,NEWID並非如此)

就這樣說,我建議你不要考慮這個方式安全。您應該認爲其他用戶總是可以猜測其他人的PIN,除非您以某種方式限制允許的猜測次數(例如,在3次嘗試後停止接受請求,類似於在3次錯誤的PIN輸入之後銀行對您的銀行卡進行綁定。)

+0

的評論也許我可以使用像你建議的開始,並將其加入到該行的ID創建一個唯一的ID - 將工作? – Josh 2010-07-26 17:13:12

+0

是的,如果您在行ID的末尾添加3個附加數字,那會起作用。我可能會追加一個簡單的隨機數字到行ID,而不是唯一標識符,這可能更有效。 – mdma 2010-07-26 18:58:19

1

你想要的是一個GUID

http://en.wikipedia.org/wiki/Globally_unique_identifier

大多數語言都有某種生成此...谷歌搜索將幫助API的;)

+1

OMG,你會爲我指定一個GUID作爲我的PIN碼,並讓我輸入所有這些亂碼?我不得不把這件事寫下來,因爲沒有辦法記住那麼長的字符串。 – DOK 2010-07-26 16:32:21

+0

關鍵是我不需要guid,因爲它太長了,我只需要它是唯一的表。 – Josh 2010-07-26 16:35:23

0

怎麼樣具有缺省值NEWID()的UNIQUEIDENTIFIER類型列?

這將爲每一行生成一個新的GUID。

+0

再次我不需要一個GUID - 請參閱@smdrager – Josh 2010-07-26 16:36:21

0

請記住,通過要求唯一的PIN碼(這是不常見的),您將限制允許的最大用戶數到PIN規範。你確定你想要嗎?

一個不是很優雅的解決方案,但它的工作原理是使用UNIQUE字段,然後循環嘗試插入隨機生成的PIN,直到插入成功。

0

您可以使用以下命令來生成BIGINT或其他數據類型。

SELECT CAST(ABS(CHECKSUM(NEWID()))%2000000000+1 as BIGINT) as [PIN] 

這產生了1到20億的數字。您將模擬某種程度的隨機性,因爲它來自NEWID函數。您也可以根據需要格式化結果。

這並不能保證唯一性。我建議你在PIN列上使用唯一的約束。而且,創建新PIN的代碼應該在分配值之前檢查新值是否是唯一的。

0

使用隨機數字。

SET @uid = ROUND(RAND()* 100000)

更稀疏的值是在表中,更好的工作的。如果分配值的數量變大與可用值的數量有關係,那麼它就不能正常工作。

一旦生成號碼,您有幾個選項。 1)在重試循環內插入值。如果您遇到重複錯誤,請重新生成該值(或嘗試值+/- 1)並重試。 2)生成值並查找MAX和MIN現有唯一標識符。

DECLARE 
    @uid INTEGER 
SET @uid = ROUND(RAND() * 10000, 1) 
SELECT @uid 
SELECT MAX(uid) FROM table1 WHERE uid < @uid 
SELECT MIN(uid) FROM table1 WHERE uid > @uid 

如果已經分配了隨機值,則MIN和MAX值將爲您提供一系列可用的值。

+0

OP想要「在表格中獨一無二的PIN」......您的實施起初可能會感覺正確,但碰撞接近50%的機會少於2500行。有關更多信息,請參見http://en.wikipedia.org/wiki/Birthday_problem。 – 2014-09-19 14:47:04

相關問題