在准备发布 Doctrine DBAL 4 时,我想将基于自动增量的表的标识列迁移到“串行”类型列,如下所述:
包含一个很好的脚本和一切。
问题是这个脚本运行这个:
-- change the dependency between column and sequence to internal
UPDATE pg_depend
SET deptype = 'i'
WHERE (classid, objid, objsubid) = ('pg_class'::regclass, seqid, 0)
AND deptype = 'a';
由于我的数据库作为托管数据库托管在 DigitalOcean 上,因此我的
doadmin
用户没有足够的权限直接修改此表:
ERROR: permission denied for table pg_depend CONTEXT: SQL statement "UPDATE pg_depend SET deptype = 'i' WHERE (classid, objid, objsubid) = ('pg_class'::regclass, seqid, 0) AND deptype = 'a'" PL/pgSQL function upgrade_serial_to_identity(regclass,name) line 31 at SQL statement
如何在无权更改此用户的权限或此表权限的情况下执行此迁移?
像这样修改目录表是危险的,并且可能会导致数据损坏。如果有一种快速简单的方法来做到这一点,为什么这么复杂?
给定一个这样的表:
\d s
Table "laurenz.s"
Column │ Type │ Collation │ Nullable │ Default
════════╪═════════╪═══════════╪══════════╪═══════════════════════════════
id │ integer │ │ not null │ nextval('s_id_seq'::regclass)
Indexes:
"s_pkey" PRIMARY KEY, btree (id)
切换到使用标识列的快速而干净的方法如下:
-- make the change atomic
BEGIN;
-- prevent concurrent access to the table
LOCK s;
-- get the current sequence value
SELECT last_value FROM s_id_seq;
last_value
════════════
1000
(1 row)
-- get rid of the sequence
DROP SEQUENCE s_id_seq CASCADE;
NOTICE: drop cascades to default value for column id of table s
-- turn "id" into an identity column, start the sequence a little higher
ALTER TABLE s ALTER id ADD GENERATED ALWAYS AS IDENTITY (START 1100);
-- done
COMMIT;
现在桌子没问题了:
\d s
Table "laurenz.s"
Column │ Type │ Collation │ Nullable │ Default
════════╪═════════╪═══════════╪══════════╪══════════════════════════════
id │ integer │ │ not null │ generated always as identity
Indexes:
"s_pkey" PRIMARY KEY, btree (id)