“sub_groups”上的“auto_increment”可以在数据库级别强制执行吗?

时间:2010-10-30 01:57:52

标签: sql mysql ruby-on-rails constraints

在Rails中,我有以下

class Token < ActiveRecord
  belongs_to :grid
  attr_accessible :turn_order
end

当您插入新令牌时,turn_order应自动递增。但是,它只应该为属于同一网格的令牌自动递增。

所以,以4个代币为例:
Token_1属于Grid_1,插入时turn_order应为1 Token_2属于Grid_2,插入时turn_Order应为1。

如果我将Token_3插入Grid_1,则插入时turn_order应为2 如果我将Token_4插入Grid_2,则插入时turn_order应为2。

还有一个额外的约束,想象一下我执行@Token_3.turn_order = 1,现在@Token_1必须自动将其turn_order设置为2,因为在这些“子组”中可能没有turn_order碰撞。

我知道MySQL有auto_increment,我想知道是否有任何逻辑可以在数据库级别应用来强制执行这样的约束。基本上在查询的子组内进行auto_increment,这些子组基于外键。

这是否可以在数据库级别处理,或者我是否应该努力在应用程序层实现坚如磐石的约束?

3 个答案:

答案 0 :(得分:1)

我的观点:应用级别的坚如磐石的限制。你可以让它在SQL中工作 - 我看到有些人做了一些非常棒的东西。许多SQL逻辑曾经被触发器中的东西所取代,但我最近并没有看到太多。

这更像是业务逻辑,你绝对可以在Ruby中完成它,而不必将自己包裹在树中。而且......人们将能够看到测试并阅读代码。

答案 1 :(得分:1)

如果我理解你的问题,那么你可以使用以下两种方法之一(innodb vs myisam)。就个人而言,我采取了innodb之路,因为我是myisam不支持的聚簇索引的粉丝,我更喜欢性能而不是我需要键入多少行代码,但决定权是你的......

http://dev.mysql.com/doc/refman/5.0/en/innodb-table-and-index.html

Rewriting mysql select to reduce time and writing tmp to disk

完整的sql脚本:http://pastie.org/1259734

innodb实施(推荐)

-- TABLES

drop table if exists grid;
create table grid
(
grid_id int unsigned not null auto_increment primary key,
name varchar(255) not null,
next_token_id int unsigned not null default 0
)
engine = innodb;

drop table if exists grid_token;
create table grid_token
(
grid_id int unsigned not null,
token_id int unsigned not null,
name varchar(255) not null,
primary key (grid_id, token_id) -- note clustered PK order (innodb only)
)
engine = innodb;

-- TRIGGERS

delimiter #

create trigger grid_token_before_ins_trig before insert on grid_token
for each row
begin

declare tid int unsigned default 0;

  select next_token_id + 1 into tid from grid where grid_id = new.grid_id;

  set new.token_id = tid;

  update grid set next_token_id = tid where grid_id = new.grid_id;

end#

delimiter ;

-- TEST DATA

insert into grid (name) values ('g1'),('g2'),('g3');

insert into grid_token (grid_id, name) values
(1,'g1 t1'),(1,'g1 t2'),(1,'g1 t3'),
(2,'g2 t1'),
(3,'g3 t1'),(3,'g3 t2');

select * from grid;
select * from grid_token;

myisam实施(不推荐)

-- TABLES

drop table if exists grid;
create table grid
(
grid_id int unsigned not null auto_increment primary key,
name varchar(255) not null
)
engine = myisam;

drop table if exists grid_token;
create table grid_token
(
grid_id int unsigned not null,
token_id int unsigned not null auto_increment,
name varchar(255) not null,
primary key (grid_id, token_id) -- non clustered PK 
)
engine = myisam;

-- TEST DATA

insert into grid (name) values ('g1'),('g2'),('g3');

insert into grid_token (grid_id, name) values
(1,'g1 t1'),(1,'g1 t2'),(1,'g1 t3'),
(2,'g2 t1'),
(3,'g3 t1'),(3,'g3 t2');

select * from grid;
select * from grid_token;

答案 2 :(得分:0)

这听起来像是你想在after_save方法或观察者中处理的东西。如果模型本身不需要知道什么时候或如何增加,那么我会将业务逻辑粘在观察者身上。这种方法将使递增逻辑更能表达其他开发人员和数据库不可知。