2个auto_increment字段,其中1重置

时间:2013-10-14 18:14:39

标签: mysql database-design innodb auto-increment

我准备编写几个MySQL表来处理发票。

我的计划是将其分为3个主要表格:

create table invoice
(
  id auto_increment,
  client (foreign key),
  created (date),
  *etc*...
)

create table products
(
  id auto_increment
  *product info*...
)

create table invoice_products
(
  invoice_id (references invoice.id)
  row (resetting auto_increment)  <--THIS!!!
  product_id(references products.id)
  product_quantity INT
  primary key (invoice_id,row)
)

困境是,当创建新发票时,invoice.id是auto_incremented,这是应该的。对于invoice_products.row,我不想从每张新发票的1开始。 因此,对于每个新发票,行auto_increment将从1开始,但如果将新行添加到现有发票ID,则行ID将从其停止的位置继续。

有关如何完成此任务的任何建议?

(我希望代码的简短版本足以让你理解困境)

提前感谢任何建议!

编辑:澄清:数据库中的所有表都是InnoDB(因为大量使用外键约束)

2 个答案:

答案 0 :(得分:0)

您所要做的就是将您的桌子更改为使用MyISAM引擎。但请注意,MyISAM不支持事务和外键。

无论如何,这是一个如何工作的例子(引用manual):

  

对于MyISAM和BDB表,您可以在多列索引的辅助列上指定AUTO_INCREMENT。在这种情况下,AUTO_INCREMENT列的生成值计算为MAX(auto_increment_column)+ 1 WHERE prefix = given-prefix。当您想要将数据放入有序组时,这非常有用。

CREATE TABLE animals (
    grp ENUM('fish','mammal','bird') NOT NULL,
    id MEDIUMINT NOT NULL AUTO_INCREMENT,
    name CHAR(30) NOT NULL,
    PRIMARY KEY (grp,id)
) ENGINE=MyISAM;

INSERT INTO animals (grp,name) VALUES
    ('mammal','dog'),('mammal','cat'),
    ('bird','penguin'),('fish','lax'),('mammal','whale'),
    ('bird','ostrich');

SELECT * FROM animals ORDER BY grp,id;
  

返回:

+--------+----+---------+
| grp    | id | name    |
+--------+----+---------+
| fish   |  1 | lax     |
| mammal |  1 | dog     |
| mammal |  2 | cat     |
| mammal |  3 | whale   |
| bird   |  1 | penguin |
| bird   |  2 | ostrich |
+--------+----+---------+
  

在这种情况下(当AUTO_INCREMENT列是多列索引的一部分时),如果删除任何组中具有最大AUTO_INCREMENT值的行,则重用AUTO_INCREMENT值。即使对于MyISAM表也会发生这种情况,因为通常不会重复使用AUTO_INCREMENT值。

     

如果AUTO_INCREMENT列是多个索引的一部分,MySQL将使用以AUTO_INCREMENT列开头的索引生成序列值(如果有)。例如,如果animals表包含索引PRIMARY KEY(grp,id)和INDEX(id),则MySQL将忽略PRIMARY KEY以生成序列值。因此,该表将包含单个序列,而不是每个grp值的序列。

如您所见,您的主键和auto_increment设置已经正确。只需更改为MyISAM。


如果您不想使用MyISAM,您也可以在选择时进行计算。

SELECT
ip.*,
@row := IF(@prev_inv != invoice_id, 1, @row + 1) AS `row`,
@prev_inv := invoice_id
FROM invoice_products ip
, (SELECT @row:=1, @prev_inv:=NULL) vars
ORDER BY invoice_id

第三种可能性当然是在数据库外计算它。我会留给你:)。

答案 1 :(得分:-1)

为此您无法使用auto_increment列。在每次插入之前,您应该查询实际发票的最大值(行)+ 1。