PostgreSQL无法将现有列设置为标识
因此,我已经阅读了几十篇帮助材料,似乎博士后经常改变工作方式。我想做的是,将一个现有列设置为IDENTITY,使其成为唯一的主键并自动递增。我在网络上找到了3种解决方案:PostgreSQL无法将现有列设置为标识,sql,database,postgresql,Sql,Database,Postgresql,因此,我已经阅读了几十篇帮助材料,似乎博士后经常改变工作方式。我想做的是,将一个现有列设置为IDENTITY,使其成为唯一的主键并自动递增。我在网络上找到了3种解决方案: id integer NOT NULL PRIMARY KEY GENERATED ALWAYS AS IDENTITY id serial NOT NULL PRIMARY KEY SERIAL id bigint NOT NULL DEFAULT nextval(some_seq) 第三个似乎是一个硬编码的解决方案,如果
id integer NOT NULL PRIMARY KEY GENERATED ALWAYS AS IDENTITY
id serial NOT NULL PRIMARY KEY SERIAL
id bigint NOT NULL DEFAULT nextval(some_seq)
第三个似乎是一个硬编码的解决方案,如果我有,比如说,500个表,则不太可行,因为我需要针对每个PK的500个序列号,所以我不能这样做
第二种方法已经过时,不再被专家推荐
这就给我留下了第一个解决方案,出于某种原因,我根本无法对我的“现有”表执行此操作。我已经从网上尝试了100种解决方案。以下是我从Stackoverflow尝试的一个来源:
而且。。。令人惊讶的是,同样的方法根本不适用于我。我尝试了以下查询:
ALTER TABLE db.table_name ALTER COLUMN id SET NOT NULL, ALTER id ADD GENERATED AS ALWAYS IDENTITY;
这给了我一个非常模糊的错误,没有任何信息:
ERROR: syntax error at or near ADD
有什么问题吗?我甚至不能用GUI添加这个,它给出了同样的错误。如果有帮助的话,我的服务器正在Linux Ubuntu机器上运行PostgreSQL v9.6.9
所以,我看了几十份帮助材料
但不是,这似乎是真正的官方手册?我不明白为什么这么多人乐于接受互联网上随机陌生人的建议,却忽视了官方手册
好像
博士后经常改变工作方式
AFAIK此自动生成的主键设置已更改一次。二十多年来。如果这个变化率对你来说太大了,那么我强烈建议你避免使用网络编程或移动应用程序
我想说的是
要做的是,将现有列设置为标识,以便它是唯一的主列
关键点和自动增量本身。我总共找到了3种解决方案
在网上:
id integer NOT NULL PRIMARY KEY GENERATED ALWAYS AS IDENTITY
id serial NOT NULL PRIMARY KEY SERIAL
id bigint NOT NULL DEFAULT nextval(some_seq)
第三个似乎是一个硬编码的解决方案,如果我
比如说,有500张表,因为我需要500个序列号
反对每一次PK,所以我不能这样做
这正是第二个解决方案所做的。我不明白为什么有500个序列是你做不到的。假设你已经设法让自己处于一个位置,你有500张桌子,你没有正确设置在第一位
如果有帮助的话,我的服务器正在Linux Ubuntu机器上运行PostgreSQL v9.6.9
的确如此
让我们不要在互联网上随意闲逛,让我们看看实际的postgresql.org手册:
没有提到身份,是吗?难怪它会抱怨你的语法
它在当前文档中,因为他们在版本10中添加了该功能
因此,由于您似乎在没有考虑需求的情况下创建了500个表,因此您面临着自己动手的前景
richardh=> CREATE TABLE t (id integer not null primary key, a text);
CREATE TABLE
richardh=> INSERT INTO t VALUES (1, 'aaa'), (2, 'bbb');
INSERT 0 2
richardh=> CREATE SEQUENCE t_id_seq;
CREATE SEQUENCE
richardh=> ALTER TABLE t ALTER COLUMN id SET DEFAULT nextval('t_id_seq');
ALTER TABLE
richardh=> SELECT setval('t_id_seq', max(id)) FROM t;
setval
--------
2
(1 row)
richardh=> INSERT INTO t VALUES (DEFAULT, 'ccc');
INSERT 0 1
richardh=> SELECT * FROM t ORDER BY id;
id | a
----+-----
1 | aaa
2 | bbb
3 | ccc
(3 rows)
那里——没那么可怕吧
显然,您可以使用plpgsql和一些EXECUTE命令编写脚本,或者使用一些regex grep+transform魔术创建一个外部sql脚本
注意,这里的关键限制是序列没有直接附加到表。如果删除一个表,那么序列将保持不变。一个关键的优势(可能不适用于您的用例)是您可以在多个表之间共享序列号(或者实际上由应用程序直接使用,而根本不存储在表中)
<> P>因为你似乎不喜欢改变,我应该指出,版本9.6将在几年内结束(可能是2022/2023),你可能希望考虑到目前最新版本(2020年7月版本12)的长期稳定性。 < P>只是澄清所说的:
不要使用序列号
对于新应用程序,应改用标识列
您应该什么时候开始?
- 如果您需要对早于版本10的PostgreSQL的支持
- 在与表继承的某些组合中(请参见此处)
- 更一般地说,如果从多个表中使用相同的序列,尽管在这些情况下,显式声明可能比串行类型更可取
serial
。有一天,当您升级Postgres时,您可以考虑更改为始终作为标识生成的
当需要更改时,此(官方文档中引用的)功能有助于促进更改。您在哪里找到您尝试的语法?仅供参考,您的第二个语法不正确。它应该是id serial NOT NULL主键
。而且也不是过时的,只是补充了一种更新的方法。第二种和第三种方法是同一事物的变体。谢谢你的帮助Richard,这确实有帮助。因此,与其直接攻击我的工作方式,对我的实际工作几乎一无所知,不如让我来教育你。我正在将整个生产环境从MSSQL迁移到Postgres,MSSQL有一种不同的自动递增键的方式。再次感谢您,我正在尝试您的解决方案,will brb。@HaiderGhulam如果您要迁移整个生产环境,请自己泡一杯好茶或咖啡,然后坐下来先阅读手册。这四个小时花得很好。这正是我想要确认的,谢谢戈登。