mysql唯一编号生成

Posted

技术标签:

【中文标题】mysql唯一编号生成【英文标题】:mysql unique number generation 【发布时间】:2011-05-21 21:32:31 【问题描述】:

我想通过 clean mysql 生成一个唯一的随机整数(从 10000 到 99999)身份;有什么想法吗?

我不想通过循环(生成数字 -> 在数据库中检查它)在 php 中生成这个数字,因为我想在 mySQL 查询中使用一些智能解决方案。

【问题讨论】:

独特于什么,表中的其他条目? 检查这将需要一个自定义函数,随着时间的推移,随着可用号码池的耗尽,该函数将逐渐变慢。即:生成随机#,查表,存在吗?重新生成,检查表,是否存在?... 如果这是为了为每一行生成唯一 ID,请按照我的回答使用 auto_increment 字段 - 这就是它们的用途。 :-) @hippoout 意味着您想要一个不在表格列中的给定范围内的数字?您是否也想跟踪以前的输出,即不允许查询以后产生相同的数字? @middaparka 是的 auto_increment 以预定义的顺序生成订单,但 OP 要求提供唯一的随机整数。我也需要这样一个数字,我使用了创建检查周期 - 但我更喜欢更好的方法。 【参考方案1】:

虽然看起来有些尴尬,但可以通过以下方式实现目标:

SELECT FLOOR(10000 + RAND() * 89999) AS random_number
FROM table
WHERE random_number NOT IN (SELECT unique_id FROM table)
LIMIT 1

简单地说,它生成N个随机数,其中N是表行数,过滤掉表中已经存在的那些,并将剩余的集合限制为一个。

在大桌子上可能会有点慢。为了加快速度,您可以从这些唯一 ID 创建一个视图,并使用它来代替嵌套的 select 语句。

编辑:删除引号

【讨论】:

有一点需要注意,这可能会导致问题,这要求table 中至少有一条记录。否则不返回随机数。 不要使用引号!它将是一个字符串,将被视为数字0 @unclenorton 我在“where 子句”中不断收到> 1054 - Unknown column 'random_number'。 如何使用此查询更新现有字段??【参考方案2】:

构建一个从序号到 1 到 1M 范围内的随机 id 值的查找表:

create table seed ( i int not null auto_increment primary key );
insert into seed values (NULL),(NULL),(NULL),(NULL),(NULL),
                        (NULL),(NULL),(NULL),(NULL),(NULL);

insert into seed select NULL from seed s1, seed s2, seed s3, seed s4, seed s5, seed s6;
delete from seed where i < 100000;

create table idmap ( n int not null auto_increment primary key, id int not null );
insert into idmap select NULL, i from seed order by rand();

drop table seed;

select * from idmap limit 10;

+----+--------+
| n  | id     |
+----+--------+
|  1 | 678744 |
|  2 | 338234 |
|  3 | 469412 |
|  4 | 825481 |
|  5 | 769641 |
|  6 | 680909 |
|  7 | 470672 |
|  8 | 574313 |
|  9 | 483113 |
| 10 | 824655 |
+----+--------+
10 rows in set (0.00 sec)

(这一切在我的笔记本电脑上运行大约需要 30 秒。您只需为每个序列执行一次。)

现在您有了映射,只需跟踪已使用的数量(另一个表中的计数器或 auto_increment 键字段)。

【讨论】:

【参考方案3】:

我在这里为解决方案苦苦挣扎了一段时间,然后意识到如果列有 NULL 条目,它就会失败。我用下面的代码重写了这个;

SELECT FLOOR(10000 + RAND() * 89999) AS my_tracker FROM Table1 WHERE "tracker" NOT IN (SELECT tracker FROM Table1 WHERE tracker IS NOT NULL) LIMIT 1

在这里拉小提琴; http://sqlfiddle.com/#!2/620de1/1

希望对你有帮助:)

【讨论】:

【参考方案4】:

我能想到的唯一合理的想法是创建一个具有有限 ID 池的表,并在使用它们时将它们从该表中删除。这些键可以是唯一的,并且可以创建一个脚本来生成该表。然后,您可以通过从可用键中生成随机选择来提取其中一个键。我说“半途而废”是合理的,老实说,这是一种慷慨的方式,但它胜过随机生成密钥,直到你创建一个独特的密钥。

【讨论】:

【参考方案5】:

我在 Cakephp 2.4.7 中实现的解决方案是创建一个带有一个 auto_incremental 类型字段的表

CREATE TABLE `unique_counters` (
  `counter` int(11) NOT NULL AUTO_INCREMENT,
  `field` int(11) NOT NULL,
  PRIMARY KEY (`counter`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

然后我创建了一个 php 函数,以便每次插入新记录时,读取生成的 id 并立即删除它。 Mysql 保持其内存计数器状态。在您重置 mysql 计数器或运行 TRUNCATE TABLE 操作之前,生成的所有数字都是唯一的

在Cakephp中创建的Model下面找到全部实现

App::uses('AppModel', 'Model');
/**
 * UniqueCounter Model
 *
 */
class UniqueCounter extends AppModel 

/**
 * Primary key field
 *
 * @var string
 */
    public $primaryKey = 'counter';

/**
 * Validation rules
 *
 * @var array
 */
    public $validate = array(
        'counter' => array(
            'numeric' => array(
                'rule' => array('numeric'),
                //'message' => 'Your custom message here',
                //'allowEmpty' => false,
                //'required' => false,
                //'last' => false, // Stop validation after this rule
                //'on' => 'create', // Limit validation to 'create' or 'update' operations
            ),
        ),
    );

    public function get_unique_counter()
        $data=array();
        $data['UniqueCounter']['counter']=0;
        $data['UniqueCounter']['field']=1;

        if($this->save($data))
            $new_id=$this->getLastInsertID();
            $this->delete($new_id);
            return($new_id);
        
        return(-1);
    

任何对结果所属范围的检查都可以在同一函数中通过操作获得的结果来实现

【讨论】:

【参考方案6】:

RAND() 函数将生成一个随机数,但保证唯一性。在 MySQL 中处理唯一标识符的正确方法是使用 AUTO_INCREMENT 声明它们。

例如,下表中的 id 字段将不需要在插入时提供,并且始终递增 1:

CREATE TABLE animal (
     id INT NOT NULL AUTO_INCREMENT,
     name CHAR(30) NOT NULL,
     PRIMARY KEY (id)
);

【讨论】:

谢谢,但我需要随机数(这是我的问题),而不是自动增量 嗯,好的。但是,如果没有更多信息,这听起来像是个坏主意。【参考方案7】:

我尝试使用这个answer,但它对我不起作用,所以我不得不稍微改变一下原来的查询。

SELECT FLOOR(1000 + RAND() * 89999) AS random_number
FROM Table
WHERE NOT EXISTS (SELECT ID FROM Table WHERE Table.ID=random_number) LIMIT 1

【讨论】:

【参考方案8】:

在你想要唯一随机的字段上创建唯一索引#

然后运行

Update IGNORE Table Set RandomUniqueIntegerField=FLOOR(RAND() * 1000000);

【讨论】:

【参考方案9】:

我担心为什么你想这样做,但你可以简单地使用:

SELECT FLOOR(RAND() * 1000000);

查看完整的MySQL RAND documentation 了解更多信息。

但是,我希望您不要使用它作为唯一标识符(如果这是您所追求的,请在适当大的无符号整数字段上使用 auto_increment attribute),我想知道您为什么要使用 MySQL为此而不是脚本语言。你想达到什么目的?

【讨论】:

以上是关于mysql唯一编号生成的主要内容,如果未能解决你的问题,请参考以下文章

如何生成唯一订单号

SQlSERVER生成唯一编号

如何使用redis生成唯一编号及原理

模板方法模式 生成唯一编号

订单流水号(唯一编号)的生成

为dynamodb生成12位唯一编号?