2

我将编写几个 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 (因为大量使用外键约束)

4

2 回答 2

0

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

无论如何,这是一个如何工作的示例(引用手册):

对于 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 列开头的索引生成序列值,如果有的话。例如,如果动物表包含索引 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

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

于 2013-10-15T08:26:56.423 回答
-1

为此,您不能使用 auto_increment 列。您应该在每次插入之前查询实际发票的 max(row) + 1。

于 2013-10-14T18:22:49.897 回答