我正在尝试生成coupen代码以提供折扣。我试过Math.Random()
,但我不确定它是否会确保每次都有一个唯一的代码?
此外,我尝试使用“Oracle”的dbms_random.string
实用程序生成随机数,但它也不保证唯一代码。
有谁知道这样做的好算法?
我正在使用java和oracle来开发代码。
编辑:在查看几个回复后,我想补充一点,我必须在表格中存储每个生成的代码。生成的代码应该是字母数字。
答案 0 :(得分:3)
您可以使用Java UUID class。它生成随机的128位字母数字字符串。重复弦的可能性是天文数字低。
具体做法是:
import java.util.UUID
.
.
String uniqueString = UUID.randomUUID().toString()
.
.
答案 1 :(得分:1)
随机是随机的,但你正确地确定了这并不意味着唯一。
您需要将已使用的代码存储在某处(如数据库后面),然后在创建新代码时扫描记录。
实际上,您可能希望预先生成100(或1000或10,000)优惠券,存储它们,并根据需要分配它们。
答案 2 :(得分:1)
我会结合随机数+序列号。这为您提供了一个独特的随机数,因为序列号是唯一的。
否则你需要做一个反复试验的方法。也许提前节省运行时间。假设您有一张带有唯一索引coupon_id的表“coupon-keys”。您生成随机密钥然后插入它。如果不是唯一的,则捕获插入失败,并在生成足够的优惠券密钥之前重试。此外,您还有一个“已使用”列,每次您提供优惠券时,您都会更新该列以跟踪仍有的优惠券号码。
答案 3 :(得分:1)
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函数中以处理任何碰撞。例如。使用UNIQUE约束并在INSERT失败时捕获异常。 (正如Bob Jarvis建议的那样。)
答案 4 :(得分:0)
以下是我的建议:
您的表格应该类似于
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,表示尚未生成唯一代码。然后输入一个循环,只要'code unique'标志仍为FALSE,循环就会继续。然后生成优惠券代码并将其存储到数据库中。如果代码是唯一的,那么一切都会很好,将设置'code unique'标志,并退出循环。但是,如果代码不唯一,则INSERT语句将失败并显示DUP_VAL_ON_INDEX异常。这将发生,因为COUPON_CODE是COUPONS表上的主键,并且我们知道主键有三个属性:它必须是非NULL,如果必须永远不会更改,并且它必须是唯一的。 (为了我们的目的,我们可以在COUPONS.COUPON_CODE上使用UNIQUE约束并获得相同的效果)。如果由于生成的优惠券代码不唯一而抛出DUP_VAL_ON_INDEX异常,则将输入异常处理程序,其中代码将完全不执行任何操作;也就是说,'code unique'标志将保持FALSE,代码将退出异常处理程序,并且因为'code unique'标志仍为FALSE,循环将重新开始,其中将生成另一个代码,等等,等等,直到最终生成一个唯一的代码并且INSERT成功。
这可能看起来很多工作,但如果选择优惠券代码生成算法,它将不会产生大量冲突,因此不必经常循环。考虑到环境,IMO这是一个合理的解决方案 - 在PL / SQL中,您依靠使用数据库来完成一些繁重的任务,例如保证唯一性。你可以花费大量的时间来尝试提出一种永远不会产生重复的真正的代码生成算法,或者你可以想出一些好的 - 如果不是很完美的东西并且使用数据库来确保最终选择的代码最终是唯一的。因人而异。如果不是特别好地利用时间,那么实现One True算法可以带来很多乐趣。 : - )
分享并享受。
答案 5 :(得分:0)
创建一个字母数字字符数组,代表优惠券代码的所有有效字符。让我们说它是所有上下字母的字母。
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();
因此,生成一个随机数,将其缩短为字符串,然后将其插入数据库。如果插入因碰撞而失败,则重试。碰撞应该是相当罕见的,并且只有在它们发生时才具有最小的成本。您的优惠券代码应保持简短且易于输入。