PostgreSQL列类型转换形式bigint到bigserial

k s*_*mar 20 sql database postgresql persistence

当我尝试通过alter命令更改表中列的数据类型时...

alter table temp alter column id type bigserial;
Run Code Online (Sandbox Code Playgroud)

我明白了

ERROR:  type "bigserial" does not exist
Run Code Online (Sandbox Code Playgroud)

如何将数据类型从bigint更改为bigserial?

Nic*_*nes 25

文档中所述,SERIAL不是数据类型,而是其他命令集合的快捷方式.

因此,虽然您无法通过更改类型来更改它,但您可以通过自己运行这些其他命令来实现相同的效果:

CREATE SEQUENCE temp_id_seq;
ALTER TABLE temp ALTER COLUMN id SET NOT NULL;
ALTER TABLE temp ALTER COLUMN id SET DEFAULT nextval('temp_id_seq');
ALTER SEQUENCE temp_id_seq OWNED BY temp.id;
Run Code Online (Sandbox Code Playgroud)

如果删除表/列,则更改所有者将确保删除序列.它还将为您提供pg_get_serial_sequence()函数中的预期行为.

坚持tablename_columnname_seq命名约定是必要的,以说服像pgAdmin这样的工具报告此列类型BIGSERIAL.请注意,即使最初将列声明为SERIAL类型,psql和pg_dump也将始终显示基础定义.

从Postgres 10开始,您还可以选择使用SQL标准标识列,该可以无形地处理所有这些,并且您可以轻松地将其添加到现有表中:

ALTER TABLE temp ALTER COLUMN id
  ADD GENERATED BY DEFAULT AS IDENTITY
Run Code Online (Sandbox Code Playgroud)

  • @Amalgovinus:基本上,是的.Postgres实际上并没有跟踪列是否被创建为"SERIAL"类型.如果你查看一个带有"BIGSERIAL"的表的`pg_dump`输出,你只会看到一个`BIGINT`和一个序列(创建`BIGINT`并且你自己的序列与使用`BIGSERIAL'完全相同`关键字).请注意,从Postgres 10开始,您可以选择将其转换为[标识列](https://blog.2ndquadrant.com/postgresql-10-identity-columns/). (3认同)

Vao*_*sun 8

ALTER为了使其自动递增,从列BIGINTEGER到的列BIGSERIAL将不起作用.BIGSERIAL它不是一个真正的类型,它是一个自动化PKSEQUENCE创建的技巧.

相反,您可以自己创建序列,然后将其指定为列的默认值:

CREATE SEQUENCE "YOURSCHEMA"."SEQNAME";

ALTER TABLE "YOURSCHEMA"."TABLENAME"
   ALTER COLUMN "COLUMNNAME" SET DEFAULT nextval('"YOURSCHEMA"."SEQNAME"'::regclass);
ALTER TABLE "YOURSCHEMA"."TABLENAME" ADD CONSTRAINT pk PRIMARY KEY ("COLUMNNAME");
Run Code Online (Sandbox Code Playgroud)

  • 请注意,这将*不*用现有值填充列.因此,如果存在"NULL"或非唯一的行,则添加"PRIMARY KEY"约束将失败.(你假设用户还没有主键.`SERIAL`不仅仅是PK,而'SERIAL`并不意味着'SERIAL PRIMARY KEY`).另外,如果表有现有行,你需要`setval`序列以确保它从第一个空闲标识符开始,首先"锁定"表以防止并发`INSERT`s. (2认同)