在多次删除/插入之后,表的键序列似乎已达到其限制(2147483647),并且 postgres 的 nextval() 不会返回新的索引值。好处是这个表的主键(id)不用作外键,所以我可以搞乱它。
该表中有 3741003 条记录,但最后给定的 id 是 2146658815。
我该如何解决这个问题? (除了创建一个 python 脚本,这是我目前的 B 计划)
有没有办法通过 postgres 将该表的所有 id“重新创建”为从 1 开始到 3741003 结束的统一序列?
更新:这是我收到的错误:
*** SQL ERROR ***
DataError('nextval: reached maximum value of sequence "data_observeddata_id_seq" (2147483647)\n')
对于你的问题:
有没有办法通过 postgres 将该表的所有 id“重新创建”为从 1 开始到 3741003 结束的统一序列?
答案是肯定的,但我无法充分强调这些操作的危险性,尽管你可能认为这是多么平凡。
在我解释该方法之前,您需要尽一切努力避免这样做,这里有 2 个替代解决方案,它们也可以同样有效,而且没有风险。
基本上,这些替代方案是您应该使用的。
如果表中当前保存的值全部高于某个阈值,则它们适用(通常,序列从生成正值开始;根据您的评论,这就是您的情况。)。
下次您的表格被截断时,不要忘记使用(文档此处)重置序列:
TRUNCATE MyTable RESTART IDENTITY
我们想要的是按照文档使序列循环。
ALTER SEQUENCE IF EXISTS data_observeddata_id_seq MINVALUE -2147483647 CYCLE
这将使下一次对
nextval
的调用成功,并且您将获得超过 20 亿个可用值。但是,如果应用程序加载表的内容,您必须确保它可以在 PK 为负值的情况下执行此操作(下一个解决方案也是如此)。
SELECT setval('data_observeddata_id_seq', -2147483647)
如果 PK 列中的最小值接近 20 亿,您可以将序列重置为 0。根据您的评论,您被迫让序列生成负值,这与上面具有相同的约束。
与前一个解决方案相比,该解决方案的缺点是,在桌子上的下一个
TRUNCATE
之后,序列将仅获得 20 亿左右的值可供使用,而解决方案 1 也通过使用负值将范围加倍。
在您决定应用此解决方案之前,让我重复一遍这应该是您最后的选择。如果数据库/表是由其他人创建的并且您不完全确定它的用途,则尤其如此。
首先确认:
使用 psql 备份表,如此答案中所述。
然后,将表格复制到新表格中。
BEGIN;
/* Create a backup */
CREATE TABLE MyTable_backup AS SELECT * FROM MyTable;
控制,如果OK,则提交并进入下一步。
BEGIN;
/* Truncate table (in Postgres, TRUNCATE can be rolled back) */
TRUNCATE MyTable RESTART IDENTITY;
控制,如果OK,则提交并进入下一步。
BEGIN;
/* Insert records back into the table, with ids being generated by the sequence */
INSERT INTO MyTable(<all columns except your primary key>)
SELECT <same list of field as above> FROM MyTable_backup;
控制,如果OK,则提交并进入下一步。
DROP TABLE MyTable_backup
观察一段时间后,您可以删除备份。