Mysql 自定义序列生成器(如 oracle)

Posted

技术标签:

【中文标题】Mysql 自定义序列生成器(如 oracle)【英文标题】:Mysql custom sequence generator ( like oracle) 【发布时间】:2011-03-21 20:10:44 【问题描述】:

我希望每个表有两个 auto_increment 列,但是 mysql 只允许一个 auto_increment 列。因此,我尝试使用自己的表复制 oracle 序列。

这是架构。

create table logical_id_seq (
    logical_id int auto_increment,
    primary key(logical_id)
);

create table mytable (
    physical_id int auto_increment,
    logical_id int not null references parent(logical_id),
    data varchar(20),
    version_start_date datetime not null,
    version_end_date datetime not null,
    primary key(physical_id),
    foreign key (logical_id) references logical_id_seq(logical_id),
    unique key (logical_id,version_start_date,version_end_date)
);

因此,logical_id_seq 表用作序列生成器。

创建新实体:

    将新条目插入logical_id_seq。 从logical_id_seq 中读取last_insert_id()。 使用上述值在表中插入新行。

让我给你更多关于logical_id 和physical_id 的上下文。我想设计一个时间旅行数据库,这意味着我想要给定任何时间戳(现在或过去)的数据库状态。所以,我有 version_start_date 和 version_end_date。

您能否告诉我我的序列生成器方法是否有副作用。

【问题讨论】:

我很困惑。有两个 ID 列的原因是什么? 所以,我想跟踪对行的修改。因此,我使用版本开始日期和结束日期来跟踪在任何时间点哪一行是有效的。 问题中说“谢谢”有错吗:-) @Algorist:是创建一个允许您保留版本历史记录的表的想法 - 也就是说,您不是用更新的版本覆盖一行,而是创建一个新行,以便旧的不坏? 是的,你是对的@Mike。 【参考方案1】:

根据您的表类型(IIRC,它是 MyISAM 和 BDB),您可以使用自动增量的巧妙技巧。

create table component_core ( 
    component_id int auto_increment, 
    primary key(component_id) 
); 

create table component_history ( 
    component_id int not null, 
    version_id int auto_increment, 
    data varchar(20), 
    version_start_date datetime not null, 
    version_end_date datetime not null, 
    primary key(component_id,version_id) 
); 

在创建全新组件时插入到component_core,然后在插入到component_history时使用该自动递增的ID作为component_id,并且对于每个不同的component_id,version_id自动递增字段将从1向上编号。插入对 component_history 的更改时,使用原始 component_id,但允许 version_id 正常自动递增。在这种情况下,auto_increment 列的生成值计算为 MAX(auto_increment_column) + 1 WHERE component_id=given-component_id。

Insert a new component_core
Retrieve the last autoincremented value from component_core (1)
Insert a new component_history using the component_id from component_core
Insert a new component_history using the same component_id
Insert a new component_history using the same component_id
Insert a new component_core
Retrieve the last autoincremented value from component_core (2)
Insert a new component_history using the component_id from component_core
Insert a new component_history using the same component_id

表格现在将包含

component_core

component_id
1
2

component_history

component_id version_id
1            1
1            2
1            3
2            1
2            2

不确定该技术是否有任何帮助,尤其是因为它仅限于特定的表类型(我相信它在 MyISAM 中有效,但您失去了使用 MyISAM 的事务控制)

编辑

参考:http://dev.mysql.com/doc/refman/5.1/en/example-auto-increment.html

【讨论】:

【参考方案2】:

所以,我想跟踪对行的修改 (...)

我建议在实施您自己的解决方案之前查看Hibernate Envers:

Envers 项目旨在实现持久类的轻松审计/版本控制。您所要做的就是使用@Audited 注释您想要审计的持久类或其某些属性。对于每个被审计的实体,将创建一个表,其中将保存对该实体所做的更改的历史记录。然后,您可以轻松检索和查询历史数据。

【讨论】:

以上是关于Mysql 自定义序列生成器(如 oracle)的主要内容,如果未能解决你的问题,请参考以下文章

ORACLE实现自定义序列号生成

如何为 Django Model PK 使用自定义 Oracle 序列?

Oracle数据库导入Excel铺底数据 -含自动插入生成自定义序列号

Oracle数据库导入Excel铺底数据 -含自动插入生成自定义序列号

Oracle序列生成器

强制获取序列下一个值/当前值(oracle函数)