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

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

感谢您的输入。

有帮助吗?

解决方案

您意识到这很可能导致堆栈溢出,对吗?随着客户数量的增加,找不到可接受的帐号的可能性也会增加。

另外,为什么不能只使用连续的帐号并每次加一呢?使用这种方法,您只需读取数据库中当前的最大 id 并递增它。

抱歉这么直白,但你的解决方案是解决问题的糟糕方法。它将使用大量内存(因为堆栈可能无限增长),并且会对数据库进行大量昂贵的调用。

你真的应该考虑其他一些方法:
我强烈建议您每次创建客户时只增加客户编号。事实上,如果您正确设置数据库(在 id 列上自动递增),您甚至不必设置 id。每当您插入新客户时,都会为您设置 ID。

其他提示

我真的不认为这可以归结为递归与递归。随着数据集的增长以及随机数生成未正确实现,两者都容易出现问题。我想到了两个想法:

. 。GUID

如果需要一个真正唯一的 ID,并且需要尽可能少的努力,请考虑使用 GUID,您的数据库很可能能够在插入时为您分配,如果不是在代码中创建的话。尽管它不是很用户友好,但它保证是唯一的。但是,与插入时数据库生成的顺序 AccountRecordId 相结合,您将获得可靠的组合

. 。复合键:随机+顺序

解决所有需求的一种方法是从 5 位(或更多)的连续数据库密钥创建一个复合帐号,然后再创建另外 5 位随机数字,尽管表面上感觉有点笨拙。如果随机数重复也没关系,因为顺序 ID 将保证整个帐号的唯一性

这里不需要使用递归调用。在函数中运行一个简单的 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

但是,如果此代码用于玩具以外的任何东西,则随机生成和测试是生成唯一帐号的次优方法。

看起来不错,但我认为你需要某种模具条件,在你放弃之前你会让这个运行多少次?

我知道这在巨大的数字范围内似乎不太可能,但可能会出现问题,让您回到之前的调用,这会再次调用自己,令人作呕。

按顺序生成帐号存在安全风险 - 您应该找到其他算法来完成此操作。

或者,您可以维护一个单独的表,其中包含生成的已知唯一帐号的缓冲区。该表应该有一个自动递增的整数 id。当您需要帐号时,只需提取缓冲区中索引最低的记录并将其从该表中删除即可。有一些定期运行的进程来补充缓冲区并确保其具有容量>>正常使用。优点是最终用户创建帐号所花费的时间基本上是恒定的。

另外,我应该注意到处理开销或递归或迭代的风险,真正的问题是确定性和重复数据库查询的开销。我喜欢 TheZenker 的随机+顺序解决方案。保证生成唯一的 id,而不增加不必要的开销。

这里不需要使用递归。一个简单的循环同样快并且消耗更少的堆栈空间。

你可以把它放在 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

为什么不:

lock_db
do
    account_num <= generate number
while account_num in db

put row with account_num in db

unlock_db

为什么不让数据库处理这个问题?在 SQL Server 中,您可以只拥有一个从 100000000 开始的标识列。或者您可以在您拥有的任何数据库中使用 sql。只需获取最大 id 加 1 即可。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top