我正在尝试弄清楚如何在 Postgres 中表示自动增量键,具体取决于您是使用 SERIAL 类型还是使用 IDENTITY 创建它。
当我使用此 DDL 创建带有 SERIAL 主键的表时:
CREATE TABLE public.test_change_column (
id SERIAL PRIMARY KEY NOT NULL
)
我得到一个名为“test_change_column_id_seq”的序列,并为列 id 指定默认值
nextval('test_change_column_id_seq'::regclass)
如果我使用此 DDL 创建一个没有 SERIAL 和主键的表:
CREATE TABLE public.test_change_column (
id INTEGER PRIMARY KEY NOT NULL GENERATED ALWAYS AS IDENTITY,
)
创建序列,但 id 的默认值未设置为 nextval('test_change_column_id_seq'::regclass)。相反,is_identity 列设置为“YES”。
如果您创建的列没有自动增量,则无法在稍后阶段使用 SERIAL 添加它:
ALTER TABLE public.test_change_column ALTER COLUMN id TYPE serial;
这会导致错误“类型“串行”不存在”。
使用 IDENTITY 方法,您可以使用此 DDL 添加自动增量:
ALTER TABLE public.test_change_column ALTER COLUMN id ADD GENERATED BY DEFAULT AS IDENTITY;
此 SQL 将显示 postgres 如何存储 2 种不同方法的元数据:
SELECT column_name, column_default, is_identity
FROM information_schema.columns
WHERE table_name = 'test_change_column';
删除自动增量时,根据您使用的是序列号还是身份标识,自动增量的删除方式有所不同。
如果使用串行类型创建自动增量,则必须更改COLUMN id DROP DEFAULT。这不会删除关联的序列表。
如果使用 IDENTITY 创建自动增量,则必须 ALTER COLUMN id DROP IDENTITY。这也会删除序列表。
将列更改为标识列(并添加 PK 约束)就足够了,也是正确的做法(
serial
伪类型的使用不鼓励)
您可以看到,例如
psql
将此正确报告为标识列:
arthur=> CREATE TABLE public.test_change_column (id INTEGER NOT NULL);
CREATE TABLE
arthur=> \d public.test_change_column
Table "public.test_change_column"
Column | Type | Collation | Nullable | Default
--------+---------+-----------+----------+---------
id | integer | | not null |
arthur=> ALTER TABLE public.test_change_column ALTER COLUMN id ADD GENERATED BY DEFAULT AS IDENTITY;
ALTER TABLE
arthur=> ALTER TABLE public.test_change_column ADD CONSTRAINT test_change_column_pkey PRIMARY KEY(id);
ALTER TABLE
arthur=> \d public.test_change_column
Table "public.test_change_column"
Column | Type | Collation | Nullable | Default
--------+---------+-----------+----------+----------------------------------
id | integer | | not null | generated by default as identity
Indexes:
"test_change_column_pkey" PRIMARY KEY, btree (id)
您还可以通过插入一行来验证默认设置是否正常工作:
insert into public.test_change_column default values;
将创建一个新行并增加
id
值。
此类列将显示在
information_schema.columns
中并带有 is_identity = 'YES'
,而不是具有默认值。
我建议使用
generated always as identity
,这样你就不会意外地绕过序列的生成(结果是序列和表中的值不再“同步”)。
创建表。
CREATE TABLE public.test_change_column (
id INTEGER NOT NULL
);
一行修改表格:
ALTER TABLE
public.test_change_column ALTER COLUMN id ADD GENERATED BY DEFAULT AS IDENTITY,
ADD CONSTRAINT test_change_column_pkey PRIMARY KEY(id);
\d test_change_column
Table "public.test_change_column"
Column | Type | Collation | Nullable | Default
--------+---------+-----------+----------+----------------------------------
id | integer | | not null | generated by default as identity
Indexes:
"test_change_column_pkey" PRIMARY KEY, btree (id)
IDENTITY
列有一个与之关联的序列,其使用方式与 serial
列一样。它只是没有显示为 DEFAULT
。要找到底层序列:
select pg_get_serial_sequence ('public.test_change_column', 'id');
pg_get_serial_sequence
----------------------------------
public.test_change_column_id_seq
select * from public.test_change_column_id_seq ;
last_value | log_cnt | is_called
------------+---------+-----------
1 | 0 | f
您可以使用此处的
IDENTITY
命令来操作上述内容ALTER TABLE:
ALTER [ COLUMN ] column_name ADD GENERATED { 始终 |默认 } AS IDENTITY [ (sequence_options) ]
更改[列]列名{设置生成{始终|默认情况下} |设置序列选项 |重新启动[[WITH]重新启动]}[...]
更改 [列] 列名 删除标识 [如果存在]
更新
从这里串行类型:
数据类型smallserial、serial和bigserial不是真正的类型,而仅仅是创建唯一标识符列的符号方便(类似于其他一些数据库支持的AUTO_INCRMENT属性)。在当前的实现中,指定:
CREATE TABLE 表名 ( 串行名称 );
相当于指定:
CREATE SEQUENCE 表名_列名_seq AS 整数;
CREATE TABLE 表名 ( colname 整数 NOT NULL DEFAULT nextval('tablename_colname_seq') );
ALTER SEQUENCE tablename_colname_seq 属于 tablename.colname;
因此,我们创建了一个整数列,并安排其默认值从序列生成器分配。应用 NOT NULL 约束以确保不能插入空值。 (在大多数情况下,您还希望附加 UNIQUE 或 PRIMARY KEY 约束以防止意外插入重复值,但这不是自动的。)最后,序列被标记为“由”列“拥有”,以便它如果删除列或表,该列或表也会被删除。
因此,如果您想要
ALTER
一个表来复制 serial
“类型”,您将需要执行上述各个步骤:
CREATE TABLE public.test_change_column (id INTEGER NOT NULL);
create sequence test_change_column_seq;
alter
table test_change_column alter COLUMN id
set default nextval('test_change_column_seq'),
ADD CONSTRAINT test_change_column_pkey PRIMARY KEY(id);
alter sequence test_change_column_seq owned by test_change_column.id;
\d test_change_column
Table "public.test_change_column"
Column | Type | Collation | Nullable | Default
--------+---------+-----------+----------+---------------------------------------------
id | integer | | not null | nextval('test_change_column_seq'::regclass)
Indexes:
"test_change_column_pkey" PRIMARY KEY, btree (id)