Mysql:复合主键中的autoincrement字段,用于其他字段的每个唯一组合

时间:2013-09-22 21:35:08

标签: mysql mysql-workbench

我有一个带有复合主键的Mysql表 我需要主键的一个字段分别为其他两个字段的每个唯一对自动增量。
例如:

Book_Name | Author_Name |章
Book1 |作者1 | 1
Book1 |作者1 | 2
Book1 |作者1 | 3
Book2 |作者2 | 1
Book2 |作者2 | 2
Book2 |作者2 | 3
Book3 |作者3 | 1
Book3 |作者3 | 2
Book3 |作者3 | 3个


有谁知道如何在Mysql Workbench中完成这项工作?

1 个答案:

答案 0 :(得分:8)

只有(书籍,作者,章节)才能成为主键,并且章节只能在一种情况下为每个独特的(书籍,作者)组合自动增加:

存储引擎必须为MyISAM

像这样定义的MyISAM表将完全符合您的预期,从每个唯一(a,b)的“1”开始列`c`:

CREATE TABLE `aa_test` (
  `a` varchar(48) NOT NULL,
  `b` varchar(48) NOT NULL,
  `c` int(11) NOT NULL AUTO_INCREMENT,
  PRIMARY KEY (`a`,`b`,`c`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

然而,不要这样做

至少出于以下原因:

首先,您不应该使用MyISAM。它是一种非常古老的技术恐龙,它不是事务性的,并且在涉及腐败和崩溃恢复时它不像InnoDB那样强大。您应该使用InnoDB,而MyISAM中的这种遗留行为并不是以不同方式做到这一点的理由。

其次,这并不适合使用自动增量。实际上,自动增量应仅用于作为代理值所需的值,但在现实世界中没有实际意义。

第三,您的表格似乎没有精心设计,甚至可能不在2nd normal form中。

基于这种结构,必须有两件事情之一:

书籍的每一章都可以有不同的作者,这打破了尝试自动增加(书籍,作者)的全部意义......或者(更有可能)每一行都存在作者属性(书,章)是多余的。

可以说,这个表中唯一的候选键是(书,章),如果作者不依赖于书和章,那么该表不在2NF中。

此外,您不应该在每行中存储图书的名称。任何给定的数据应该只出现在关系数据库的单个表中的单个行中的单个列中,其他每个都通过键引用它(例如,“book_id”在这里引用单个“id” “book”表,其中包含本书“标题”的列。)

然后,我的回答是建议你不要试图解决正确的问题,并且应该考虑重新设计你的结构,以便作者是一本书中的书的属性,每本书只有一行,然后你这个表有(书,章),你的应用程序可以手动填充这些章节号。

或者,如果您坚持自动生成这些值,则可以使用BEFORE INSERT触发器计算插入时的相应值,包含如下逻辑:

IF IFNULL(NEW.Chapter,0) = 0 THEN  
  SET NEW.Chapter = (SELECT COUNT(1) FROM this_table_name x
                      WHERE x.Book_Name = NEW.Book_Name
                        AND x.Author_Name = NEW.Author_Name) + 1;
END IF;

具有此逻辑的触发器可用于任何存储引擎。

IFNULL()是必需的,因为MySQL在列不可为空时触发触发器之前历史上将null强制为0,即使此行为不正确。