Mysql:其他字段的每个唯一组合的复合主键中的自动增量字段

Mysql:其他字段的每个唯一组合的复合主键中的自动增量字段,mysql,mysql-workbench,Mysql,Mysql Workbench,我有一个带有复合主键的Mysql表。 我需要主键的其中一个字段,以便为其他两个字段的每一个唯一对分别自动递增。 例如: 书名|作者|章节 Book1 | Author1 | 1 书1 |作者1 | 2 第1册作者第3册 书籍2 |作者2 | 1 书籍2 |作者2 | 2 书2 |作者2 | 3 第三册作者1 第三册作者第二册 Book3| Author3|3 有人知道如何在Mysql Workbench中做到这一点吗?只有在一种情况下,(书籍、作者、章节)才可能成为主键,章节才可能为每个唯一

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

书名|作者|章节
Book1 | Author1 | 1
书1 |作者1 | 2
第1册作者第3册
书籍2 |作者2 | 1
书籍2 |作者2 | 2
书2 |作者2 | 3
第三册作者1
第三册作者第二册
Book3| Author3|3


有人知道如何在Mysql Workbench中做到这一点吗?

只有在一种情况下,(书籍、作者、章节)才可能成为主键,章节才可能为每个唯一的(书籍、作者)组合独立地自动递增:

存储引擎必须是
MyISAM

像这样定义的
MyISAM
表将完全满足您的期望,从列`c`开始为每个唯一项(A,b)设置“1”:

但是,不要这样做

至少出于以下原因:

首先,你不应该使用MyISAM。这是一个非常古老的技术恐龙,它不是事务性的,而且当涉及到损坏和崩溃恢复时,它的健壮性不如InnoDB。您应该使用InnoDB,而MyISAM中的这种遗留行为并不是改变这种做法的好理由

第二,这不是一个真正适当的使用自动增量。自动增量实际上应该只用于需要作为代理值但在现实世界中没有实际意义的值

第三,您的桌子似乎设计得不好,甚至可能没有设计好

基于此结构,以下两点之一必须为真:

一本书的每一章都可能有不同的作者,这打破了试图自动增加(书,作者)的目的。。。或者(更有可能)在(书籍、章节)的每一行上都存在author属性是多余的

可以说,该表中唯一的候选键是(book,chapter),如果作者不同时依赖book和chapter,那么该表就不在2NF中

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

<>我的回答是,你不是在试图解决正确的问题,应该考虑重新设计你的结构,以便作者是一本书的一个属性,每一本书只有一行,然后你就可以用(书,章)这张表,你的应用程序可以手动填入那些章节编号。 或者,如果您坚持自动生成这些值,则可以在插入前使用
触发器来计算插入时的适当值,其中包含如下逻辑:

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时触发触发器之前将null强制为0,即使此行为不正确。

哪个字段是自动递增的?在本例中,它将是章节
自动递增
必须是主键,所以你不能有重复的书名、作者名和章节都标记为PK。主键是三者的组合。是否不可能将(Book1,Author1,1)作为主键?这仍然是一个独特的组合。谢谢你花时间向我解释这一点。我重新安排了数据库结构。我理解你的观点。但我的问题也与此类似。我有[主题,身份证,问题,答案,解释]。这里的关键是(主题,id)。我不想把桌子分开。因为科目多。那么,我应该使用你的
不做
设计还是拆分它?请advise@GopsAB现在还不清楚每一列的意思。我假设一个问题有一个或多个主题,但我不明白“答案”或“解释”中包含什么样的数据。例如,[数学,1,2+2=,4,解释]一个问题只有一个主题。
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;