当向表分区上已有该PK的分区表添加唯一索引,然后添加PK时,PK创建失败,错误为multiple primary keys for table X are not allowed

为什么会出现这种限制和奇怪的错误消息?不是应该管用吗?

场景1:索引然后主键-失败

CREATE TABLE tst_t (
    c1 int4 NOT NULL,
    c2 int8 NOT NULL,
    c3 int8 NOT NULL
)
PARTITION BY LIST (c1);

CREATE TABLE tst_t_988 PARTITION OF tst_t (
    CONSTRAINT pk_tst_t_988 PRIMARY KEY (c1)
) FOR VALUES IN (988);

create unique index pk_tst_t on tst_t using btree (c1);

alter table tst_t add primary key (c1);

-- SQL Error [42P16]: ERROR: multiple primary keys for table "tst_t_988" are not allowed

场景2:没有索引则PK-Works

drop table tst_t;

CREATE TABLE tst_t (
    c1 int4 NOT NULL,
    c2 int8 NOT NULL,
    c3 int8 NOT NULL
)
PARTITION BY LIST (c1);

CREATE TABLE tst_t_988 PARTITION OF tst_t (
    CONSTRAINT pk_tst_t_988 PRIMARY KEY (c1)
) FOR VALUES IN (988);

-- this time not creating the index
--create unique index pk_tst_t on tst_t using btree (c1);

alter table tst_t add primary key (c1);

-- works

场景3:只对已分区的表进行索引,然后使用PK-Works

drop table tst_t;

CREATE TABLE tst_t (
    c1 int4 NOT NULL,
    c2 int8 NOT NULL,
    c3 int8 NOT NULL
)
PARTITION BY LIST (c1);

CREATE TABLE tst_t_988 PARTITION OF tst_t (
    CONSTRAINT pk_tst_t_988 PRIMARY KEY (c1)
) FOR VALUES IN (988);

-- this time index on ONLY partitioned table
create unique index pk_tst_t on only tst_t using btree (c1);

alter table tst_t add primary key (c1);

-- works

推荐答案

如果分区上已有主键,则可以在分区表上添加主键,方法是首先仅在分区表上添加无效的主键,然后将分区上的主键索引作为分区附加到该索引.一旦索引在所有表分区上都有一个分区,主键就会自动生效:

CREATE TABLE tst_t (
    c1 int4 NOT NULL,
    c2 int8 NOT NULL,
    c3 int8 NOT NULL
)
PARTITION BY LIST (c1);

CREATE TABLE tst_t_988 PARTITION OF tst_t (
    CONSTRAINT pk_tst_t_988 PRIMARY KEY (c1)
) FOR VALUES IN (988);

ALTER TABLE ONLY tst_t ADD CONSTRAINT tst_t_pkey PRIMARY KEY (c1);

ALTER INDEX tst_t_pkey ATTACH PARTITION pk_tst_t_988;

\d tst_t
         Partitioned table "laurenz.tst_t"
 Column │  Type   │ Collation │ Nullable │ Default 
════════╪═════════╪═══════════╪══════════╪═════════
 c1     │ integer │           │ not null │ 
 c2     │ bigint  │           │ not null │ 
 c3     │ bigint  │           │ not null │ 
Partition key: LIST (c1)
Indexes:
    "tst_t_pkey" PRIMARY KEY, btree (c1)
Number of partitions: 1 (Use \d+ to list them.)

\d+ tst_t_pkey
            Partitioned index "laurenz.tst_t_pkey"
 Column │  Type   │ Key? │ Definition │ Storage │ Stats target 
════════╪═════════╪══════╪════════════╪═════════╪══════════════
 c1     │ integer │ yes  │ c1         │ plain   │ 
primary key, btree, for table "laurenz.tst_t"
Partitions: pk_tst_t_988
Access method: btree

Postgresql相关问答推荐

函数返回查询执行plpgsql时不存在列

带有regex表达式的Postgres SQL

如何将存储的、生成的列添加到非常大的表中?

为什么我的应用程序接收的是空值而不是布尔值?

从数据集中提取彼此喜欢的用户(&Q;)

如何在PostgreSQL中 Select 最近30天内的开始日期?

JPA将没有时区的Postgres时间戳调整为服务器时区

使用 pgx 扫描范围类型

返回行值和行计数的总和

从dump文件中恢复三张表遇到的问题

如何将 JSONB 对象数组合并为 PostgreSQL 中的单个对象

MERGE 语句的锁定级别

函数将多列作为单列而不是多列返回

如何从 WSL 连接到 windows postgres 数据库

knex: Select 特定日期范围内的行

PostgreSQL 不区分大小写的 SELECT 数组

避免 created_at 和 updated_at 由 sequelize 自动生成

在 postgres 中创建超级用户

PostgreSQL 中跨多个表的索引

在同一台机器上创建多个 Postgres 实例