【问题标题】:How to generate Unique coupen code? [duplicate]如何生成唯一优惠券代码? [复制]
【发布时间】:2013-04-22 00:09:33
【问题描述】:

我正在尝试生成优惠码以提供折扣。我试过Math.Random(),但我不确定它是否每次都能保证一个唯一的代码?。

我也尝试过使用“Oracle”的dbms_random.string 实用程序来生成随机数,但它也不能保证唯一的代码。

有谁知道这样做的好算法吗?

我正在使用 java 和 oracle 开发代码。

编辑:看了几个回复后,我想补充一点,我必须将每个生成的代码都存储在表中。并且生成的代码应该是字母数字的。

【问题讨论】:

  • 优惠券代码存储在db中?
  • 不能简单地创建一个序列并使用序列号作为优惠券代码?
  • @lok​​i:我必须生成带有可以很容易猜到的序列的 coupen 代码。因此,任何人都可以尝试使用下一个数字并错误地使用 coupen 代码。序列根本不是解决方案。
  • 不,我不认为上述问题与我的问题重复。
  • 我同意:提议的主题不是这个主题的重复。

标签: java oracle plsql


【解决方案1】:

您可以使用 Java UUID class。它生成随机的 128 位字母数字字符串。一个字符串重复的可能性是天文数字的低。

具体来说:

import java.util.UUID
.
.
String uniqueString = UUID.randomUUID().toString()
.
.

【讨论】:

  • 不知道为什么这没有被接受。 UUID 生成类似 32 个字母数字值,因此发生冲突的概率为 (1/(26 (字母)+ 10 (数字))^(32))^2=(1/(36^32))^2。 ...你永远不会发生碰撞。
  • 独一无二?当然。根据是在商店还是在线(可以选择复制/粘贴),输入优惠券代码可能会有点长。
【解决方案2】:

随机是随机的,但您正确识别这并不意味着唯一。

您需要将已使用的代码存储在某个地方(例如返回数据库),然后在创建新代码时扫描记录。

实际上,您可能希望预先生成 100(或 1000 或 10,000)张优惠券,存储它们,并根据需要分配它们。

【讨论】:

  • 首先我正在查找表中的代码,但是重新检查现有代码一点也不可取,因为我们必须批量生成coupen。
【解决方案3】:

我会结合随机数 + 序列号。这为您提供了一个唯一的随机数,因为序列号是唯一的。

否则,您需要采用试错法。也许提前节省运行时间。假设您有一个带有唯一索引 coupon_id 的表“coupon-keys”。您生成随机密钥,然后将其插入。如果不是唯一的,您会捕获插入失败并重试,直到生成足够的优惠券密钥。此外,您还有一个“已使用”列,每次发放优惠券时,您都会更新该列以跟踪仍然可用的优惠券号码。

【讨论】:

  • 这不能保证唯一性。例如,按顺序 10051、10052 发出的随机数 1234、1233 会发生冲突(11285==11285)。如果您打算将它们转换为字符串并连接,那么“123”+“456”可能会与“12”+“3456”发生冲突。
  • 第一种方法不能保证唯一性,但我认为第二种方法可以正常工作。
  • 是的,我的意思是固定长度的随机数,用连接的零填充。但这只是快速的技巧,真的。现在在回答了一天之后,我必须承认我认为我个人最想要的解决方案是如果失败循环方法则生成和插入重试。如果随机数足够长,就不应该进行那么多试验。
  • 这是一个生成独特的好技巧。即使我们有最后 4 个字符作为序列的一部分,如果它是字母数字,我们也可以生成 36^4 个优惠券,即 1679616。如果字母数字是小写和大写,那么可以生成 62^4 个组合。
【解决方案4】:

创建一个字母数字字符数组,代表您的优惠券代码的所有有效字符。假设都是大写和小写字母字符。

String chars[]="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ".toCharArray();

您可以将任何整数转换为更短的代码,基本上是通过执行数字基数转换(尽管顺序相反)。

int max=100000000;
int random=(int) (Math.random()*max);
StringBuffer sb=new StringBuffer();
while (random>0) {
    sb.append(chars[random % chars.length]);
    random /= chars.length;
}
String couponCode=sb.toString();

因此,生成一个随机数,将其缩短为一个字符串,然后将其插入到您的数据库中。如果插入因碰撞而失败,则重试。碰撞应该是相当罕见的,并且在它们发生时只会产生最小的成本。您的优惠券代码应该简短且易于输入。

【讨论】:

    【解决方案5】:

    从 10g 开始的 Oracle 包含 dbms_crypto 包以允许生成真正的随机序列。

    http://docs.oracle.com/cd/B19306_01/appdev.102/b14258/d_crypto.htm#i1000605.

    在获得一些随机 RAW 字节后,可以使用 utl_encode 包将这些字节编码为合适的字母数字字符串。

    http://psoug.org/reference/utl_encode.html

    如果优惠券代码足够长,冲突应该是不可行的,但您仍然可以将优惠券创建包装在 PL/SQL 函数中以处理任何冲突。例如。如果 INSERT 失败,请使用 UNIQUE 约束并捕获异常。 (正如 Bob Jarvis 建议的那样。)

    【讨论】:

      【解决方案6】:

      以下是我的建议:

      你的桌子应该看起来像

      CREATE TABLE COUPONS
        (COUPON_CODE NUMBER
           CONSTRAINT PK_COUPONS
             PRIMARY KEY
             USING INDEX);        -- plus whatever other fields you need
      

      您生成唯一代码的代码应该类似于

      DECLARE
        nCoupon_code    NUMBER;
        bCode_unique     BOOLEAN;
      BEGIN
        bCode_unique := FALSE;
      
        WHILE bCode_unique = FALSE LOOP
          BEGIN
            nCoupon_code := GENERATE_COUPON_CODE;  -- function to generate a coupon code
      
            INSERT INTO COUPONS (COUPON_CODE)
              VALUES (nCoupon_code);
      
            bCode_unique := TRUE;
          EXCEPTION
            WHEN DUP_VAL_ON_INDEX THEN
              NULL;  -- Fall through, loop back to the top, generate new code, continue
          END;
        END LOOP;  -- bCode_unique
      END;
      

      这里发生的事情是程序首先将'code unique'标志设置为FALSE,表示尚未生成唯一代码。然后进入一个循环,只要“代码唯一”标志仍然为 FALSE,就会继续。然后生成优惠券代码并将其存储到数据库中。如果代码是唯一的,一切都会很好,“代码唯一”标志将被设置,并且循环将被退出。但是,如果代码不是唯一的,则 INSERT 语句将失败并出现 DUP_VAL_ON_INDEX 异常。这是因为 COUPON_CODE 是 COUPONS 表上的主键,并且我们知道主键具有三个属性:它必须是非 NULL,如果不能更改,它必须是唯一的。 (出于我们的目的,我们可以在 COUPONS.COUPON_CODE 上使用 UNIQUE 约束并获得相同的效果)。如果由于生成的优惠券代码不唯一而引发 DUP_VAL_ON_INDEX 异常,则将输入异常处理程序,代码将完全不执行任何操作;也就是说,“代码唯一”标志将保持为 FALSE,代码将从异常处理程序中退出,并且由于“代码唯一”标志仍然为 FALSE,循环将重新开始,生成另一个代码,等等,以此类推,直到最终生成唯一代码并且 INSERT 成功。

      这可能看起来需要做很多工作,但如果优惠券代码生成算法选择得当,它就不会产生很多冲突,因此不必过于频繁地循环。 IMO 考虑到环境,这是一个合理的解决方案 - 在 PL/SQL 中,您指望使用数据库来完成一些繁重的工作,例如保证唯一性。您可以花费大量时间来尝试提出一个永远不会、永远可能生成重复的真正代码生成算法,或者您可以提出一些即使不完美也很好的东西并与数据库一起使用确保最终选择的代码是唯一的。 YMMV。实现一个真正的算法可能会很有趣,如果不是特别好地利用时间的话。 :-)

      分享和享受。

      【讨论】:

        猜你喜欢
        • 2011-06-01
        • 1970-01-01
        • 2014-12-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-07-24
        • 2016-06-14
        • 1970-01-01
        相关资源
        最近更新 更多