【问题标题】:Mysql: autoincrement field in composite primary key for each unique combination of other fieldsMysql:其他字段的每个唯一组合的复合主键中的自动增量字段
【发布时间】:2013-09-27 17:50:21
【问题描述】:

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

书名 |作者姓名 |章节
书1 |作者1 | 1
书1 |作者1 | 2
书1 |作者1 | 3
书2 |作者2 | 1
书2 |作者2 | 2
书2 |作者2 | 3
书3 |作者3 | 1
书3 |作者3 | 2
书3 |作者3 | 3


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

【问题讨论】:

  • auto_incrementing 是哪个字段?
  • 在示例中为章节
  • auto_increment 必须是主键,所以不能有重复项
  • Book_Name、Author_Name 和章节都标记为 PK。作为主键是三者的组合。是否不可能将 (Book1,Author1,1) 作为主键?它仍然是一个独特的组合。

标签: mysql mysql-workbench


【解决方案1】:

只有在一种情况下,(book,author,chapter) 才有可能成为主键,并且对于每个唯一的 (book,author) 组合,chapter 独立地自动递增:

存储引擎必须是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中也可能没有。

根据此结构,必须满足以下两项之一:

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

可以说,该表中唯一的候选键是 (book,chapter),如果作者不依赖于书和章节,则该表不在 2NF 中。

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

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

或者,如果您坚持自动生成这些值,您可以使用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 历来在列不可为空时触发触发器之前将空值强制为 0,即使此行为不正确。

【讨论】:

  • 感谢您花时间向我解释这一点。我重新安排了我的数据库结构。
  • 我理解你的观点。但我的问题也与此类似。我有[主题、id、问题、答案、解释]。这里的关键是(主题,id)。我不想拆分桌子。因为科目多。那么我应该使用您的don't do 设计还是应该拆分它?请指教
  • @GopsAB 不清楚这些列的含义。我假设一个问题有 1 个或多个主题,但我不明白“答案”或“解释”中包含哪些类型的数据。
  • 例如,[数学, 1, 2+2=, 4, 解释。] 一个问题只有一个主题。
猜你喜欢
  • 2012-01-31
  • 1970-01-01
  • 2014-01-27
  • 2015-06-04
  • 2016-03-24
  • 1970-01-01
  • 2011-09-25
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多