在 Rails 中,我有以下内容
class Token < ActiveRecord
belongs_to :grid
attr_accessible :turn_order
end
当您插入新 token 时,turn_order 应自动递增。然而,它应该只自动递增属于同一网格的 token 。
因此,以 4 个 token 为例:
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,我想知道是否有任何逻辑可以在数据库级别应用来强制执行这样的约束。基本上在查询的子组内自动递增,这些子组基于外键。
这是可以在数据库级别处理的事情,还是我应该努力在应用程序层实现坚如磐石的约束?
最佳答案
如果我正确理解你的问题,那么你可以使用以下两种方法之一(innodb 与 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;
关于sql - 可以在数据库级别强制执行 "auto_increment"上的 "sub_groups"吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4056914/