从 PostgreSQL 中的列中删除 "identity flag"
Remove "identity flag" from a column in PostgreSQL
我在 PostgreSQL 12.9 中有一些 table 被声明为
-- This table is written in old style
create table old_style_table_1 (
id bigserial not null primary key,
...
);
-- This table uses new feature
create table new_style_table_2 (
id bigint generated by default as identity,
...
);
第二个 table 似乎是使用第 10 版中引入的 声明的。
时间过去了,我们对旧的 table 进行了分区,同时保留了原始序列:
CREATE TABLE partitioned_old_style_table_1 (LIKE old_style_table_1 INCLUDING DEFAULTS) PARTITION BY HASH (user_id);
CREATE TABLE partitioned_new_style_table_2 (LIKE new_style_table_2 INCLUDING DEFAULTS) PARTITION BY HASH (user_id);
他们的 id
列的 DDL 似乎是 id bigint default nextval('old_style_table_1_id_seq') not null
和 id bigint default nextval('new_style_table_2_id_seq') not null
。
到目前为止一切正常。分区的 tables 被证明是一个很大的福音,我们决定通过删除旧的 tables 来淘汰它们。
DROP TABLE old_style_table_1, new_style_table_2;
-- [2BP01] ERROR: cannot drop desired object(s) because other objects depend on them
-- Detail: default value for column id of table old_style_table_1 depends on sequence old_style_table_1_id_seq
-- default value for column id of table new_style_table_2 depends on sequence new_style_table_2_id_seq
经过一番思考,我发现序列可能在 postgres 中有所有者,所以我选择更改它们:
ALTER SEQUENCE old_style_table_1_id_seq OWNED BY partitioned_old_style_table_1.id;
DROP TABLE old_style_table_1;
-- Worked out flawlessly
ALTER SEQUENCE new_style_table_2_id_seq OWNED BY partitioned_new_style_table_2.id;
ALTER SEQUENCE new_style_table_2_id_seq OWNED BY NONE;
-- Here's the culprit of the question:
-- [0A000] ERROR: cannot change ownership of identity sequence
所以,很显然,这一栏的 pg_attribute.attidentity 设置为 'd'
禁止我:
• 更改列的默认值:
ALTER TABLE new_style_table_2 ALTER COLUMN id SET DEFAULT 0;
-- [42601] ERROR: column "id" of relation "new_style_table_2" is an identity column
• 删除默认值:
ALTER TABLE new_style_table_2 ALTER COLUMN id DROP DEFAULT;
-- [42601] ERROR: column "id" of relation "new_style_table_2" is an identity column
-- Hint: Use ALTER TABLE ... ALTER COLUMN ... DROP IDENTITY instead.
• 完全删除身份、列或 table(新的 table 已经取决于序列):
ALTER TABLE new_style_table_2 ALTER COLUMN id DROP IDENTITY IF EXISTS;
-- or
ALTER TABLE new_style_table_2 DROP COLUMN id;
-- or
DROP TABLE new_style_table_2;
-- result in
-- [2BP01] ERROR: cannot drop desired object(s) because other objects depend on them
-- default value for column id of table partitioned_new_style_table_2 depends on sequence new_style_table_2_id_seq
我已经查找了 documentation,它提供了通往 SET IDENTITY
或 ADD IDENTITY
的方式,但没有办法删除它或更改为一次性序列而不尝试删除现有的。
➥ 那么,我怎样才能从列序列对中删除标识标志,这样它就不会影响使用该序列的其他 table?
UPD:在本地主机上尝试 运行 UPDATE pg_attribute SET attidentity='' WHERE attrelid=16816;
,仍然收到 [2BP01]
和 [0A000]
。 :/
虽然我成功执行了DROP DEFAULT
值位,但似乎是死路一条
我认为没有一种安全且受支持的方法可以做到这一点(无需修改目录)。幸运的是,序列并没有什么特别之处会导致丢弃它们成为问题。所以请稍作休息:
删除使用标识序列的默认值
记录序列的当前值
删除 table
创建具有适当 START
值的新序列
使用新序列设置新的默认值
如果您想要一个标识列,您应该在分区 table 上定义它,而不是在其中一个分区上。
我在 PostgreSQL 12.9 中有一些 table 被声明为
-- This table is written in old style
create table old_style_table_1 (
id bigserial not null primary key,
...
);
-- This table uses new feature
create table new_style_table_2 (
id bigint generated by default as identity,
...
);
第二个 table 似乎是使用第 10 版中引入的
时间过去了,我们对旧的 table 进行了分区,同时保留了原始序列:
CREATE TABLE partitioned_old_style_table_1 (LIKE old_style_table_1 INCLUDING DEFAULTS) PARTITION BY HASH (user_id);
CREATE TABLE partitioned_new_style_table_2 (LIKE new_style_table_2 INCLUDING DEFAULTS) PARTITION BY HASH (user_id);
他们的 id
列的 DDL 似乎是 id bigint default nextval('old_style_table_1_id_seq') not null
和 id bigint default nextval('new_style_table_2_id_seq') not null
。
到目前为止一切正常。分区的 tables 被证明是一个很大的福音,我们决定通过删除旧的 tables 来淘汰它们。
DROP TABLE old_style_table_1, new_style_table_2;
-- [2BP01] ERROR: cannot drop desired object(s) because other objects depend on them
-- Detail: default value for column id of table old_style_table_1 depends on sequence old_style_table_1_id_seq
-- default value for column id of table new_style_table_2 depends on sequence new_style_table_2_id_seq
经过一番思考,我发现序列可能在 postgres 中有所有者,所以我选择更改它们:
ALTER SEQUENCE old_style_table_1_id_seq OWNED BY partitioned_old_style_table_1.id;
DROP TABLE old_style_table_1;
-- Worked out flawlessly
ALTER SEQUENCE new_style_table_2_id_seq OWNED BY partitioned_new_style_table_2.id;
ALTER SEQUENCE new_style_table_2_id_seq OWNED BY NONE;
-- Here's the culprit of the question:
-- [0A000] ERROR: cannot change ownership of identity sequence
所以,很显然,这一栏的 pg_attribute.attidentity 设置为 'd'
禁止我:
• 更改列的默认值:
ALTER TABLE new_style_table_2 ALTER COLUMN id SET DEFAULT 0;
-- [42601] ERROR: column "id" of relation "new_style_table_2" is an identity column
• 删除默认值:
ALTER TABLE new_style_table_2 ALTER COLUMN id DROP DEFAULT;
-- [42601] ERROR: column "id" of relation "new_style_table_2" is an identity column
-- Hint: Use ALTER TABLE ... ALTER COLUMN ... DROP IDENTITY instead.
• 完全删除身份、列或 table(新的 table 已经取决于序列):
ALTER TABLE new_style_table_2 ALTER COLUMN id DROP IDENTITY IF EXISTS;
-- or
ALTER TABLE new_style_table_2 DROP COLUMN id;
-- or
DROP TABLE new_style_table_2;
-- result in
-- [2BP01] ERROR: cannot drop desired object(s) because other objects depend on them
-- default value for column id of table partitioned_new_style_table_2 depends on sequence new_style_table_2_id_seq
我已经查找了 documentation,它提供了通往 SET IDENTITY
或 ADD IDENTITY
的方式,但没有办法删除它或更改为一次性序列而不尝试删除现有的。
➥ 那么,我怎样才能从列序列对中删除标识标志,这样它就不会影响使用该序列的其他 table?
UPD:在本地主机上尝试 运行 UPDATE pg_attribute SET attidentity='' WHERE attrelid=16816;
,仍然收到 [2BP01]
和 [0A000]
。 :/
虽然我成功执行了DROP DEFAULT
值位,但似乎是死路一条
我认为没有一种安全且受支持的方法可以做到这一点(无需修改目录)。幸运的是,序列并没有什么特别之处会导致丢弃它们成为问题。所以请稍作休息:
删除使用标识序列的默认值
记录序列的当前值
删除 table
创建具有适当
START
值的新序列使用新序列设置新的默认值
如果您想要一个标识列,您应该在分区 table 上定义它,而不是在其中一个分区上。