将主键更改为复合主键

时间:2015-01-08 02:47:08

标签: sql postgresql database-design foreign-keys unique-constraint

我一直在为我的一个表使用“普通”(非复合)主键。现在我想将其更改为复合主键。 我的表看起来像这样:

-- Table 1
CREATE TABLE foo (
    id SERIAL PRIMARY KEY,
    id2 INT,
    ...
)

-- Table 2
CREATE TABLE bar (
    id SERIAL PRIMARY KEY,
    id_foo INT REFERENCES foo (id)
)

这里的问题是psql不想删除旧的主键,因为其他表引用它。

有没有办法在不丢弃整个数据库的情况下解决这个问题?

2 个答案:

答案 0 :(得分:1)

在删除id约束之前,您可以在PRIMARY KEY上添加冗余UNIQUE constraint。这满足了FK约束的要求。 Per documentation:

  

外键必须引用作为主键或形成唯一约束的列。

大胆强调我的。

显然,FK约束绑定到它在pg_depend中明确创建的PK约束。因此,您需要删除并稍后重新创建所有引用FK约束或混乱系统表(这是不可取的!)。最好用一个事务来保持参照完整性:

BEGIN;
ALTER TABLE bar DROP CONSTRAINT bar_id_foo_fkey;

ALTER TABLE foo 
    DROP CONSTRAINT foo_pkey
  , ADD CONSTRAINT foo_uni_id UNIQUE (id)
  , ADD PRIMARY KEY (id, id2);

ALTER TABLE bar ADD CONSTRAINT bar_id_foo_fkey
  FOREIGN KEY (id) REFERENCES foo (id);

COMMIT;

SQL Fiddle.(使用查询显示提供其他名称的商品。)

manual on ALTER TABLE中的详细信息。

这只作为中间状态才有意义。如果id保持UNIQUE NOT NULL,那么它也可能是PK。

答案 1 :(得分:1)

我认为您需要更改所有引用外键以使用新主键,对吧?因此,您将不得不删除所有这些外键,然后删除主键,然后创建新的主键,然后创建引用新主键的新外键。因此,如果有10个FK引用此表,则必须执行10滴FK,1滴旧PK,1更改以添加新PK,然后10更改以添加新FK。 / p>

我没有Postgres的实例,但我不认为有任何捷径。我想你必须完成所有22个步骤。但是你不必丢弃数据库,只需要删除所有FK。

如果你想让旧的FK继续指向旧PK,那么当你完成时它将不再是PK,那么正如Erwin所说,你应该能够在它上面添加一个独特的约束。虽然我认为他的例子是落后的,因为你必须在删除PK之前添加唯一约束,否则你会得到相同的消息。正如我所说的那样,请不要随便查看Postgres的副本。在Sql Server中,您可以添加唯一索引,然后删除pk,然后创建新的pk。我想最坏的情况是你必须放弃10个FK然后重新创建它们。