【问题标题】:Mysql auto increment alternativesMysql 自动增量替代方案
【发布时间】:2011-03-21 17:50:49
【问题描述】:

我有下表。

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

架构背后的想法是,我想跟踪对 通过检查每一行并找到任何特定日期的有效行 版本开始日期和版本结束日期。我希望我的逻辑 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)
);

【问题讨论】:

    标签: database database-design mysql


    【解决方案1】:

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

    仅为一列创建一个单独的表,以便将 auto_increment 用于额外的 auto_increment 是我能想到的最佳解决方案,通过触发器或存储过程访问。

    【讨论】:

      【解决方案2】:

      您为什么不希望有一个包含当前版本的表,然后再添加一个用于历史记录的表?然后,您使用插入到当前版本表中来生成您的 ID,并且仅在您真正需要历史记录信息时才查询历史记录表。

      【讨论】:

      • 我希望我的数据库与时间无关,从某种意义上说,数据库的数据在任何时间点都有效。
      【解决方案3】:

      现在我了解您的问题:)。改变我的答案。

      您将需要使用一些触发器,以便每当编辑某行时,逻辑 ID 会增加 1,从而找到表中可用的最大逻辑 ID。

      【讨论】:

      • 查找最大值可能会导致竞争条件并最终破坏数据。
      【解决方案4】:
      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,并用它更新父级的物理 ID(可能在触发器中)。

      现在,要查找当前记录,在 parent 中查找逻辑 id,并使用 parent.physical_id 加入“mytable”中的正确记录

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

      要查找逻辑记录的所有实例,请使用“mytable”中的logical_id。

      要插入一条全新的记录,先插入到parent中获取新的logical_id,然后将数据插入“mytable”;这就是我们允许 parent.physical_id 可以为空的原因。

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

      【讨论】:

      • 其实我想设计一个时间旅行数据库,所以没有当前状态的概念。很抱歉我没有提及,但版本开始日期和结束日期用于在任何时间点查找状态。希望现在清楚。谢谢@tpdi。
      • “时间旅行”数据库是指时间数据库,也就是“第六范式”数据库吗?
      猜你喜欢
      • 2019-10-07
      • 2013-12-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-08-22
      • 2012-03-14
      • 1970-01-01
      相关资源
      最近更新 更多