postgresql无法将现有列设置为标识

dfddblmv  于 2021-07-24  发布在  Java
关注(0)|答案(2)|浏览(254)

所以,我看了几十篇帮助材料,似乎博士后经常改变工作方式。我要做的是,将现有列设置为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)

第三个似乎是一个硬编码的解决方案,如果我有,比方说,500个表,不太可行,因为我需要500个序列号对每个pk,所以我不能这样做。
第二种是过时的方法,不再被Maven推荐。
这就留给我第一个解决方案,由于某种原因,我根本无法对我的“现有”表执行此操作。我已经尝试了100种网络解决方案。下面是我从stackoverflow中尝试的一个源代码:如何在postgresql11.1中将现有列更改为identity
还有。。。令人惊讶的是,同样的方法根本不适用于我。我尝试了以下查询:

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

有什么问题吗?我甚至不能添加这个使用图形用户界面,它给出了相同的错误。我的服务器在linux-ubuntu机器上运行postgresqlv9.6.9,如果这有帮助的话。

d5vmydt9

d5vmydt91#

只是澄清一下文件上说的:
不要使用序列号
对于新的应用程序,应该改用标识列。
. . .
你应该什么时候去?
如果您需要对早于版本10的postgresql的支持。
在某些具有表继承的组合中(但请参见此处)
更一般地说,如果从多个表中使用相同的序列,尽管在这些情况下,显式声明可能比串行类型更可取。
您的用例属于第一类。您的postgres版本早于10.0,因此 serial 很好。有一天,当你升级postgres时,你可以考虑改成 generated always as identity .
当需要改变的时候,这个博客(被官方文件引用)有一个帮助改变的功能。

k4ymrczo

k4ymrczo2#

所以,我看了很多帮助材料,
但不是,它看起来像是真正的官方手册?我不明白为什么这么多人乐于听从网络上随机陌生人的建议,却忽视了官方手册。
似乎博士后经常改变工作方式。
afaik这个自动生成的主键设置已经更改过一次。在二十多年里。如果这个变化率对你来说太大了,那么我强烈建议你避免任何与网络编程或移动应用程序有关的事情。
我要做的是,将现有列设置为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)

第三个似乎是一个硬编码的解决方案,如果我有,比方说,500个表,不太可行,因为我需要500个序列号对每个pk,所以我不能这样做。
这正是第二种解决方案的作用。我不明白为什么有500个序列是你做不到的。假设你已经设法让自己进入一个位置,你有500张table,你没有正确地设置在第一位。
我的服务器在linux-ubuntu机器上运行postgresqlv9.6.9,如果这有帮助的话。
确实如此。
我们不要在互联网上胡闹,让我们看看postgresql.org的实际手册:
https://www.postgresql.org/docs/9.6/sql-createtable.html
没有提到身份,是吗?难怪它在抱怨你的语法。
https://www.postgresql.org/docs/12/sql-createtable.html
它出现在当前文档中,因为他们在版本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 magic创建一个外部sql脚本。
注意,这里的关键限制是序列没有直接附加到表。如果删除一个表,那么序列将保持不变。一个关键的优势(这可能不适用于您的用例)是您可以在多个表之间共享序列号(或者实际上是由应用程序直接使用而根本不存储在表中)。
既然您似乎反对更改,我应该指出9.6版将在几年内(可能是2022/2023年)停止使用,您可能希望考虑使用最新版本(截至2020年7月的第12版)以保持长期稳定性。

相关问题