当前位置: 首页 > 知识库问答 >
问题:

更改PostgreSQL表中的主键

周越泽
2023-03-14

我的PostgreSQL9.3.6数据库中有users表,有两列:id另一个idid是主键,另一个id只是另一个具有唯一约束的整数列。

还有其他按主键引用用户的表。

下面是用户表说明:

Table "public.users"
        Column        |              Type              |               Modifiers                | Storage | Stats target | Description 
----------------------+--------------------------------+----------------------------------------+---------+--------------+-------------
 id                   | integer                        | not null                               | plain   |              | 
 another_id           | integer                        | not null                               | plain   |              | 

Indexes:
    "users_pkey" PRIMARY KEY, btree (id)
    "uniq_1483a5e93414710b" UNIQUE, btree (another_id)

Referenced by:
    TABLE "foo_table" CONSTRAINT "fk_4affc6e5a76ed395" FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
    TABLE "bar_table" CONSTRAINT "fk_72936b1da76ed395" FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
    TABLE "baz_table" CONSTRAINT "fk_83adbaf0a76ed395" FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE

以下是foo_表说明:

Table "public.foo_table"
    Column    |              Type              |                   Modifiers                   | Storage  | Stats target | Description 
--------------+--------------------------------+-----------------------------------------------+----------+--------------+-------------
 id           | integer                        | not null                                      | plain    |              | 
 user_id      | integer                        |                                               | plain    |              | 

Indexes:
    "foo_table_pkey" PRIMARY KEY, btree (id)
    "idx_e52ffdeea76ed395" btree (user_id)
Foreign-key constraints:
    "fk_e52ffdeea76ed395" FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE

如何将PostgreSQL表中的主键从id列替换为另一个_id列,并保持数据完整性?

共有1个答案

鄢选
2023-03-14

我花了一些时间,终于想出了一个可行的解决方案。

我将在这里发表,以备将来参考。

首先,您有三个表(foo_tablebar_tablebaz_table),它们通过外键指向您的用户表(在所有情况下称为user_id)。您需要将存储在这些列中的id从id替换为另一个_id。以下是你可以做到的:

-- We are dropping the foreign key constraint on dependant table (in other case it will prevent us from updating the values)
ALTER TABLE foo_table DROP CONSTRAINT fk_e52ffdeea76ed395;

-- Then, we're swapping values in foreign key column from id to another_id
UPDATE foo_table T SET user_id = (SELECT another_id FROM users WHERE id = T.user_id);

-- And finally we're creating new foreign key constraint pointing to the another_id instead of id
ALTER TABLE foo_table ADD CONSTRAINT fk_e52ffdeea76ed395 FOREIGN KEY (user_id) REFERENCES users (another_id) ON DELETE CASCADE;

您需要对每个依赖表重复上述查询。

您的新代码将指向该表后面的另一列。

最后,我们只需要替换主键:

-- 1. Dropping the original primary key
ALTER TABLE users DROP CONSTRAINT users_pkey

-- 2. Renaming existing index for another_id (optional)
ALTER INDEX uniq_1483a5e93414710b RENAME TO users_pkey

-- 3. Creating new primary key using existing index for another_id
ALTER TABLE users ADD PRIMARY KEY USING INDEX users_pkey

-- 4. Creating index for old id column (optional)
CREATE UNIQUE INDEX users_id ON users (id)

-- 5. You can drop the original sequence generator if you won't need it
DROP SEQUENCE users_id_seq

如果愿意,您甚至可以删除原始的id列。

我希望它能帮助别人。

 类似资料:
  • 我对SQL和MySQL非常陌生。我试图修改表中的主键列,使其自动递增。这个主键也是另一个表中的外键。由于与另一个表中的外键相关的错误,我无法修改此列。以下是错误: 我确信这很简单,但我不知道为什么,我关注的书也没有说明原因。谢谢。

  • 在这里,是主列键中的第三列。我想要做到这一点的唯一方法是将主复合键更改为。我找不到任何文档告诉我如何做到这一点。有可能吗? 或者,我是否错过了解决这个问题的“正确”方法/我是否曲解了这个问题?

  • 如何更改PostgreSQL用户的密码?

  • 问题内容: 我正在尝试使用python更改url中的主机名,并且一直在使用urlparse模块一段时间,但找不到令人满意的解决方案。例如,考虑URL: https://www.google.dk:80/barbaz 我想将“ www.google.dk”替换为“ www.foo.dk”,因此得到以下网址: https://www.foo.dk:80/barbaz。 因此,我要替换的部分是urlpa

  • 问题内容: 我是Postgresql的新手,正在使用9.3版。我有一张桌子,里面有几行。我的问题是,当我更新一行时,该行号被更改并将其移动到表中的最后一个位置。我的问题是:这是否是默认行为,因为我认为在更新行时,不应将其从其位置移开?该操作似乎就像先删除然后再插入该行。 这是示例SQL: 从今起: 将ID为1的更新后的行移动到最后一个位置。 谢谢 问题答案: 行号已更改 关系表中没有“行号”之类的

  • 我想更新表中几行的主键。如果所有行都已更新,则键将再次是唯一的,但第一行的更新会导致与第二行的键发生临时冲突。有没有优雅的方法来解决这个问题? 例子: 错误:重复的键值违反了唯一约束“pk_erichtest”