在PostgreSQL中,分区表的主键只能建立在分区键上,且不能作为外键引用。PolarDB PostgreSQL版(兼容Oracle)支持分区表使用任意列作为主键或者外键引用。
前提条件
支持的PolarDB PostgreSQL版(兼容Oracle)的版本如下:
Oracle 2.0(内核小版本2.0.14.17.0及以上)
您可通过如下语句查看PolarDB PostgreSQL版(兼容Oracle)的内核小版本的版本号:
SHOW polar_version;
参数说明
polar_pk_in_non_partition_column_mode
:用于指定非分区键上的主键所使用的索引类型,取值如下:
none
/local_pk
:不支持主键建立在非分区键上,否则会提示错误。global_index
:在非分区键上创建主键时,会使用全局索引作为约束。
使用限制
指定的主键如果包含所有分区键,则默认使用局部索引作为主键,否则使用全局索引作为主键。
指定的约束如果包含所有分区键,则默认使用局部索引作为唯一约束,否则使用全局索引作为唯一约束。
分区表的添加主键语法只能使用全局索引,因为局部索引不一定能满足约束,添加唯一约束语法也是如此。
分区表被外键引用的行不允许发生跨分区更新,因为跨分区更新本质上是一次删除和一次插入,在执行删除时会检测此行是否被外键引用。
示例
设置polar_pk_in_non_partition_column_mode
为none
,并在非分区键上创建主键。
SET polar_pk_in_non_partition_column_mode = none;
CREATE TABLE pt1 (a int, b int primary key, c varchar) PARTITION BY RANGE(a);
ERROR: unique constraint on partitioned table must include all partitioning columns
DETAIL: PRIMARY KEY constraint on table "pt1" lacks column "a" which is part of the partition key.
设置polar_pk_in_non_partition_column_mode
为global_index
,并在非分区键上创建主键。
SET polar_pk_in_non_partition_column_mode = global_index;
CREATE TABLE pt1 (a int, b int primary key, c varchar) PARTITION BY RANGE(a);
CREATE TABLE pt1_p1 PARTITION OF pt1 FOR VALUES FROM (0) TO (1);
\d pt1
Partitioned table "public.pt1"
Column | Type | Collation | Nullable | Default
--------+-------------------+-----------+----------+---------
a | integer | | |
b | integer | | not null |
c | character varying | | |
Partition key: RANGE (a)
Indexes:
"pt1_pkey" PRIMARY KEY, btree (b) GLOBAL
Number of partitions: 1 (Use \d+ to list them.)
如果分区表的主键包含了所有分区键,则使用局部索引作为主键,无论参数polar_pk_in_non_partition_column_mode
的取值是什么,此为PostgreSQL的默认行为。
CREATE TABLE pt2 (a int primary key, b int, c varchar) PARTITION BY RANGE(a);
CREATE TABLE pt2_p1 PARTITION OF pt2 FOR VALUES FROM (0) TO (1);
\d pt2
Partitioned table "public.pt2"
Column | Type | Collation | Nullable | Default
--------+-------------------+-----------+----------+---------
a | integer | | not null |
b | integer | | |
c | character varying | | |
Partition key: RANGE (a)
Indexes:
"pt2_pkey" PRIMARY KEY, btree (a)
Number of partitions: 1 (Use \d+ to list them.)
如果必须使用全局索引作为主键,可以使用修改表主键的语法。
ALTER TABLE pt2 DROP CONSTRAINT pt2_pkey;
CREATE UNIQUE INDEX pt2_pkey ON pt2 (a) GLOBAL;
ALTER TABLE pt2 ADD PRIMARY KEY USING INDEX pt2_pkey;
\d pt2
Partitioned table "public.pt2"
Column | Type | Collation | Nullable | Default
--------+-------------------+-----------+----------+---------
a | integer | | not null |
b | integer | | |
c | character varying | | |
Partition key: RANGE (a)
Indexes:
"pt2_pkey" PRIMARY KEY, btree (a) GLOBAL
Number of partitions: 1 (Use \d+ to list them.)