2010-07-26 56 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

相关问题