19

今天我发现你可以使用两列(tsql)来拥有一个主键。PK 必须是唯一的,但两列都不是(组合必须是唯一的)。

我觉得那很酷。至少有两个这样的问题我问人们在哪里对我大喊大叫,说我做错了我的(mysql)数据库,只有一个人说我做得很好。所以...这让我有些怀疑

这和我想的一样吗?

create table User(
   id INT primary key AUTO_INCREMENT ,  
   ipaddr  TEXT  NOT NULL , 
   email  TEXT  NOT NULL
);
create table test(
  a  INT  NOT NULL ,
  b  INT  NOT NULL ,
  dummy  INT  NOT NULL ,
  FOREIGN KEY (a) REFERENCES User(id),
  FOREIGN KEY (b) REFERENCES User(id),
  PRIMARY KEY(a,b)
);

我运行了以下内容,因此看来我正在做我认为的事情(组合必须是唯一的。但列中的相同值不需要是唯一的)。我应该知道什么吗?关于mysql没有人向我提到这一点一定是有原因的吗?

mysql> insert into test(a,b,dummy) select 1,1,1;
Query OK, 1 row affected (0.03 sec)
Records: 1  Duplicates: 0  Warnings: 0

mysql> insert into test(a,b,dummy) select 1,2,2;
Query OK, 1 row affected (0.03 sec)
Records: 1  Duplicates: 0  Warnings: 0

mysql> insert into test(a,b,dummy) select 2,1,3;
Query OK, 1 row affected (0.03 sec)
Records: 1  Duplicates: 0  Warnings: 0

mysql> insert into test(a,b,dummy) select 2,2,4;
Query OK, 1 row affected (0.03 sec)
Records: 1  Duplicates: 0  Warnings: 0

mysql> insert into test(a,b,dummy) select 1,2,5;
ERROR 1062 (23000): Duplicate entry '1-2' for key 'PRIMARY'
4

8 回答 8

31

你想多了:

  • 主键(无论涉及多少列)必须是唯一的
  • 你的主键是两列 a, b

因此 a 和 b一起必须是唯一的。

a 和 b 的个体值无关。

于 2013-01-08T01:32:32.707 回答
4

是的,这在 SQL 中是很正常的事情,并且可以正常工作(具有复合主键,其中多个字段共同构成一个唯一值)。

两个注意事项:

  1. 确保它是必要的。经常这样,然后就好了。但有时这表明您需要进一步规范化您的数据模型。

  2. 我在想你不想让和 ab 成为另一个表的外键,然后让它们成为你表的复合主键。如果您设置级联删除,其中一个用户 id 而不是另一个被删除,会发生什么?所以复合主键很好,但是你不想来自“不相关”的外键。

于 2013-01-08T01:40:17.557 回答
4

你的想法很好。我经常使用多字段主键,仅仅是因为它使我的数据库设计更具逻辑性、可管理性和可读性。您可以将多字段主键想象为具有唯一名称。例如:

多字段主键:

(First ,Middle, Last)

示例值:

('Michael', 'A.', 'Kline')

可能有很多人的“名字”为“Michael”和/或“中间”的名字为“A”。和/或“姓氏”“Kline”,但就您的数据库而言,只能有一个“Michael A. Kline”。

通常,多字段主键是其他表中其他主键的组合,记录内容描述了与特定键值相关的内容。例如:

Table #1: Student Records (KEY: student_id)
Table #2: Course Records (KEY: course_id)
Table #3: Student Grades (KEY: student_id, course_id)

希望这可以帮助。

于 2013-11-27T16:56:23.940 回答
3

是的,您必须注意复制您的PRIMARY_KEY,这是一个组合键,在您的情况下不会被复制。

无论如何,当您设置两个 PK 时,这意味着您的签名是PK1+PK2,因此您可以复制 PK1 或 PK2,但不能同时复制它们。

希望我有所帮助

于 2013-01-08T01:25:56.603 回答
2

还有一件事要注意:主键在 MySQL 中自动建立索引。您在主键中提到的列的顺序确实对性能很重要,如此处所述

于 2014-05-05T10:16:08.683 回答
1

我相信正在发生的事情是成对的列在一起是主要的。例如,您知道不能有重复的主列 例如:如果 col "a" 是主列,则不能有两行具有相同的 a 值。

在此示例中,您有两个初选;这意味着每个 col 对只能有一个唯一值。例如,如果 col 'a' 和 'b' 是主要的,而 'c' 不是: a|b|c 1,2,3 有效 1,4,5 有效,5,1,6 有效 9,1,10 有效

但你不能有: 9,8,10 9,8,6 因为对于那个 (9,8) 对,你只能有一个唯一的值......

这有意义吗,还是您希望我进一步详细说明?

于 2013-01-08T01:25:43.453 回答
1

ALTER TABLE TableNameDROP PRIMARY KEY, ADD PRIMARY KEY( column1, column2); 如果您之前已设置主键,请尝试此操作。

于 2018-03-19T06:02:12.270 回答
0

为了更容易解释,我将只使用一张表。创建一个包含 2 个 int 列的表,并在这两个列上创建一个 PK。就像问题一样。

create table test(
  a  INT  NOT NULL ,
  b  INT  NOT NULL ,
  PRIMARY KEY(a,b));

现在我们可以添加行,直到出现错误

insert into test values(1,1); 
Query OK, 1 row affected (0,00 sec)

insert into test values(1,2); 
Query OK, 1 row affected (0,00 sec)

insert into test values(1,1); 
ERROR 1062 (23000): Duplicate entry '1-1' for key 'PRIMARY'

这是合乎逻辑的,因为当执行最后一条语句时,构成 PK 的 2 列的组合值不再是唯一的。

允许将值 1 的 2 倍存储在 a 中,因为那不是 PK。PK 是列 a 和 b 的组合值。

于 2019-09-30T15:14:24.580 回答