您好我需要生成9位数的唯一帐号。这是我的伪代码:
function generateAccNo()
generate an account number between 100,000,000 and 999,999,999
if the account number already exists in the DB
call generateAccNo() /* recursive call */
else
return new accout number
end if
end function
该函数似乎运行良好,但我有点担心递归调用。
这是否会导致内存泄漏(apache下的PHP 5)?
这是解决这个问题的可接受方式吗?
感谢您的意见。
答案 0 :(得分:8)
你意识到这很可能导致堆栈溢出,对吧?随着客户数量的增加,未找到可接受帐号的可能性增加。
另外,为什么你不能只做连续的帐号而每次只增加一个?使用这种方法,您只需要读取数据库中当前的最大ID,然后将其递增。
很抱歉这么直率,但你的解决方案是一个解决问题的可怕方法。它将使用大量内存(因为堆栈可能无限增长)并且它将对数据库进行大量昂贵的调用。
您应该考虑其他方法:
我强烈建议您每次创建客户时都增加客户编号。实际上,如果你正确设置你的数据库(在id列上有自动增量),你甚至不必设置id。每当您插入新客户时,都会为您设置ID。
答案 1 :(得分:3)
我真的不认为它归结为递归与循环,随着数据集的增长以及随机数生成未正确实现,两者都容易出现问题。想到两个想法:
。 GUID
如果需要尽可能少的真正唯一ID,请考虑GUID,您的数据库很可能能够在插入时为您分配,如果不在代码中创建一个。尽管它不是非常用户友好,但它保证是独一无二的。但是,结合插入数据库生成的顺序AccountRecordId,您将拥有一个可靠的组合
。复合键:随机+顺序
解决所有需求的一种方法是,虽然表面上感觉有些麻烦,但是要从5位数(或更多)的连续数据库密钥创建一个复合帐号,然后再创建另外5位随机数。如果随机数重复,则无关紧要,因为序列ID将保证整个帐号的唯一性
答案 2 :(得分:2)
此处无需使用递归调用。在函数测试中运行一个简单的while循环作为条件,例如
function generateAccNo()
generate an account number between 100,000,000 and 999,999,999
while ( the account number already exists in the DB ) {
generate new account number;
}
return new account number
end function
如果此代码适用于玩具以外的其他任何内容,则随机生成和测试是生成唯一帐号的次优方法。
答案 3 :(得分:1)
看起来很好,但我认为你需要某种模具状态,在你放弃之前,你要让这个运行多少次?
我知道这个数字范围很大似乎不太可能,但有些事情可能会出错,只会让你回到之前的呼叫,这会再次召唤自己,令人烦恼。
答案 4 :(得分:1)
顺序生成帐号是一种安全风险 - 您应该找到其他算法来执行此操作。
答案 5 :(得分:1)
或者,您可以维护一个单独的表,其中包含已生成的缓冲区,已知为唯一帐号。该表应具有自动递增的整数id。如果需要帐号,只需使用缓冲区中最低索引的记录,然后从该表中删除它。有一些定期运行的过程,它补充缓冲区并确保它具有容量>>正常使用。优点是最终用户在创建帐号时所经历的时间基本上是不变的。
另外,我应该注意处理开销或递归或迭代的风险,真正的问题是确定性和重复数据库查询的开销。我喜欢TheZenker的随机+顺序解决方案。保证在不增加不必要的开销的情况下生成唯一ID。
答案 6 :(得分:0)
这里不需要使用递归。一个简单的循环同样快,并且消耗更少的堆栈空间。
答案 7 :(得分:0)
你可以把它放在while循环中:
function generateAccNo()
while (true) {
generate an account number between 100,000,000 and 999,999,999
if the account number already exists in the DB
/* do nothing */
else
return new accout number
end if
}
end function
答案 8 :(得分:0)
为什么不:
lock_db
do
account_num <= generate number
while account_num in db
put row with account_num in db
unlock_db
答案 9 :(得分:0)
为什么不让数据库处理这个?在SQL Server中,您可以拥有一个以100000000开头的标识列。或者您可以在任何db中使用sql。只需获取最大ID加1。