生成唯一帐号 - 递归调用

时间:2008-09-19 00:59:11

标签: unique records

您好我需要生成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)?

这是解决这个问题的可接受方式吗?

感谢您的意见。

10 个答案:

答案 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。