sql - 可以在数据库级别强制执行 "auto_increment"上的 "sub_groups"吗?

标签 sql mysql ruby-on-rails constraints

在 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/

相关文章:

mysql - 什么时候用 SQL 存储聚合数据有用

mysql - Rails 回滚、更改类型并再次迁移

ruby-on-rails - Rails-在初始化时执行rake任务

ruby-on-rails - 引用 has_many (Rails) 中的实例

mysql - 从具有特定元素的列记录中拆分一条或多条记录

sql - 比较同一个表中的值集

Mysql 限制性能

mysql - 从sql中删除字段

php - 如何从付款表中查找待付款客户列表

ruby-on-rails - Ruby on Rails URL 中的资源映射(RESTful API)