SQL: 用一条语句创建多个外键是否等同于用一条语句创建它们?
SQL: Is creating multiple foreign keys with one statement equivalent to creating them with one statement?
例如,我们有以下 table 定义:
CREATE TABLE table1
(
id INT UNIQUE,
name VARCHAR(100) UNIQUE,
description VARCHAR(100),
PRIMARY KEY (id, name)
);
现在我想创建另一个 table,它将具有上述复合主键的外键。下面两个语句是否等价?
1)
CREATE TABLE table2
(
id INT PRIMARY KEY,
table1_id INT,
table1_name VARCHAR(100),
FOREIGN KEY (table1_id) REFERENCES table1(id),
FOREIGN KEY (table1_name) REFERENCES table1(name)
);
2)
CREATE TABLE table2
(
id INT PRIMARY KEY,
table1_id INT,
table1_name VARCHAR(100),
FOREIGN KEY (table1_id, table1_name) REFERENCES table1(id, name),
);
我注意到在幕后 Postgre SQL 在 1) 的情况下创建了两个 FK db 对象,在 2) 的情况下创建了一个 FK 对象。一切都会一样吗?
完全没有。外键引用应该指向主键。在这种情况下,您有一个复合主键(尽管可能不需要,请参见下文)。尽管允许外键引用唯一键(有些数据库甚至允许外键引用 任何 索引列),但这不是最佳实践。
当您使用复合主键(您的第二个示例)时,您保证 id
/name
在第一个 table 中对齐。当您使用单独的引用(您的第一个示例)时,您不知道它们是对齐的,因此 id
可以引用 table1
中的一行,而 name
可以引用另一行。我怀疑这是你的意图。
无论如何,在 table 之间重复冗余数据是一种不好的做法。更好的数据模型是:
CREATE TABLE table1 (
id INT PRIMARY KEY,
name VARCHAR(100) UNIQUE,
description VARCHAR(100),
);
CREATE TABLE table2 (
id INT PRIMARY KEY,
table1_id INT,
FOREIGN KEY (table1_id) REFERENCES table1(id)
);
然后,如果你想要对应的name
,在第一个table中查找名字。
请注意,在 Postgres 中,我希望 INT
确实是 SERIAL
,因此数据库会在您插入新行时分配一个唯一的递增值。
如果你真的想要对 table1
的两个引用,那么使用两个 id 引用:
CREATE TABLE table2 (
id INT PRIMARY KEY,
table1_id INT,
table1_id_2 INT,
FOREIGN KEY (table1_id) REFERENCES table1(id),
FOREIGN KEY (table1_id_2) REFERENCES table1(id)
);
例如,我们有以下 table 定义:
CREATE TABLE table1
(
id INT UNIQUE,
name VARCHAR(100) UNIQUE,
description VARCHAR(100),
PRIMARY KEY (id, name)
);
现在我想创建另一个 table,它将具有上述复合主键的外键。下面两个语句是否等价?
1)
CREATE TABLE table2
(
id INT PRIMARY KEY,
table1_id INT,
table1_name VARCHAR(100),
FOREIGN KEY (table1_id) REFERENCES table1(id),
FOREIGN KEY (table1_name) REFERENCES table1(name)
);
2)
CREATE TABLE table2
(
id INT PRIMARY KEY,
table1_id INT,
table1_name VARCHAR(100),
FOREIGN KEY (table1_id, table1_name) REFERENCES table1(id, name),
);
我注意到在幕后 Postgre SQL 在 1) 的情况下创建了两个 FK db 对象,在 2) 的情况下创建了一个 FK 对象。一切都会一样吗?
完全没有。外键引用应该指向主键。在这种情况下,您有一个复合主键(尽管可能不需要,请参见下文)。尽管允许外键引用唯一键(有些数据库甚至允许外键引用 任何 索引列),但这不是最佳实践。
当您使用复合主键(您的第二个示例)时,您保证 id
/name
在第一个 table 中对齐。当您使用单独的引用(您的第一个示例)时,您不知道它们是对齐的,因此 id
可以引用 table1
中的一行,而 name
可以引用另一行。我怀疑这是你的意图。
无论如何,在 table 之间重复冗余数据是一种不好的做法。更好的数据模型是:
CREATE TABLE table1 (
id INT PRIMARY KEY,
name VARCHAR(100) UNIQUE,
description VARCHAR(100),
);
CREATE TABLE table2 (
id INT PRIMARY KEY,
table1_id INT,
FOREIGN KEY (table1_id) REFERENCES table1(id)
);
然后,如果你想要对应的name
,在第一个table中查找名字。
请注意,在 Postgres 中,我希望 INT
确实是 SERIAL
,因此数据库会在您插入新行时分配一个唯一的递增值。
如果你真的想要对 table1
的两个引用,那么使用两个 id 引用:
CREATE TABLE table2 (
id INT PRIMARY KEY,
table1_id INT,
table1_id_2 INT,
FOREIGN KEY (table1_id) REFERENCES table1(id),
FOREIGN KEY (table1_id_2) REFERENCES table1(id)
);