2010-07-27 82 views
0

我有下表。Mysql自动增量备选方案

create table mytable(
physical_id int auto_increment, 
logical_id int, 
data varchar(20), 
version_start_date datetime, 
version_end_date datetime, 
primary key(physical_id), 
unique key(logical_id,version_start_date, version_end_date) 
); 

架构背后的想法是,我想跟踪修改,以 每一行并通过检查 version_start_date和version_end_date发现于任何特定日期的有效行。我想我的逻辑ID为 auto_increment,但mysql只允许一个id为auto_increment。

因此,我想在创建新行时将logical_id设置为physical_id。我能够使用触发器做到这一点。

delimiter $$ 
create trigger myTrigger before insert on mytable for each row begin set 
new.logical_id = (select auto_increment from information_schema.tables 
where table_schema = database() and table_name = 'mytable') ; end$$ 
delimiter ; 

我检查了几个其他选项,http://feedblog.org/2007/06/20/portable-sequence-generation-with-mysql/http://www.redhat.com/docs/en-US/JBoss_Hibernate/3.2.4.sp01.cp03/html/Reference_Guide/Native_SQL-Custom_SQL_for_create_update_and_delete.html

的问题,这些方法是,我要创建一个新的序列表,并保持插入一条记录到该表中。

有没有更好的选择?

谢谢
巴拉

-- Update 

我不知道为什么@tpdi,为什么我需要家长,当我可以只是见下表效仿这一点。

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) 
); 

回答

0

为什么你不想要一张当前版本的表格,然后再添加一张表格作为历史记录?然后,在当前版本表中使用插入来生成您的ID,并且只在实际需要历史信息时查询历史记录表。

+0

我希望我的数据库是时间不可知的,从某种意义上说,数据库的数据在任何时间点都有效。 – Boolean 2010-07-27 17:36:02

1

这就是为什么我更喜欢将Oracle/PostgreSQL序列添加到MySQL的auto_increment和SQL Server的IDENTITY中 - 您可以为此定义多个序列。

为了使用auto_increment获得额外的auto_increment而创建一个单独的表格,这是我能想到的最好的解决方案,通过触发器或存储过程来访问。

0

现在我明白你的问题:)。改变我的答案。

您将需要使用某些触发器,以便无论何时编辑某行,逻辑ID都会增加1,找到表中可用的最大逻辑ID。

+0

查找最大值可能导致竞争条件并最终导致数据损坏。 – Boolean 2010-07-27 17:42:26

0
create table parent (
    logical_id int auto_increment, 
    physical_id int null references mytable(id) 
); 


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

要插入现有记录的新实例,插入MYTABLE ...,然后捕捉新mytable.id和更新家长与它physical_id(可能触发)。

现在,查找当前记录,查找逻辑ID在父母,并使用parent.physical_id加入到“MYTABLE”正确的记录

父指向当前有效的记录(所有的记录)放在“mytable”中。

要查找逻辑记录的所有实例,请使用“mytable”中的logical_id。要插入一个全新的记录,首先插入到父节点以获得新的logical_id,然后将数据插入到“mytable”中。这就是为什么我们允许parent.physical_id为空。

至于OP的更新:是的,你可以通过“窃取”一个序列来“模拟”,但这并不能模拟真正发生的事情。 “窃取”序列只是一个实现细节;如上所示,有两个表明确了真正发生了什么,即:“mytable”中有一个当前状态(哪个父指向),“mytable”中有0,1或许多先前的状态。这是一个更清晰的关注点分离,一个表格告诉你“任何id的当前状态”,以及一个表格,告诉你“当前状态的数据和先前状态的数据”。

+0

请检查我的更新。谢谢。 – Boolean 2010-07-27 18:27:07

+0

其实我想设计一个时间旅行数据库,所以没有当前状态的概念。对不起,我没有提到,但版本开始日期和结束日期是为了在任何时间点找到状态的目的。现在希望它清楚。谢谢@tpdi。 – Boolean 2010-07-27 20:34:19

+0

“时间旅行”数据库,你的意思是时态a.k.a.“第六范式”数据库吗? – tpdi 2010-07-27 21:14:38