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)
);