PostgreSQL: serial vs identity

若要在表上使用整数自动编号主键,可以使用 SERIAL

但是我注意到表 information_schema.columns有许多 identity_字段,实际上,您可以使用 创建一个带有 GENERATED说明符的列..。

有什么区别吗? 它们是否引入了不同的 PostgreSQL 版本? 一个版本比另一个更受欢迎吗?

56688 次浏览

serial是自动生成独特价值的“老”实现,这种价值观在 Postgres 已经存在了很长时间。但这不是 SQL 标准的一部分。

为了更符合 SQL 标准,Postgres 10引入了使用 generated as identity的语法。

底层实现仍然基于序列,定义现在符合 SQL 标准。这种新语法允许的一件事是防止意外地覆盖该值。

考虑以下表格:

create table t1 (id serial primary key);
create table t2 (id integer primary key generated always as identity);

现在当你跑的时候:

insert into t1 (id) values (1);

The underlying sequence and the values in the table are not in sync any more. If you run another

insert into t1 default_values;

You will get an error because the sequence was not advanced by the first insert, and now tries to insert the value 1 again.

第二张桌子,

insert into t2 (id) values (1);

结果:

ERROR: cannot insert into column "id"
Detail: Column "id" is an identity column defined as GENERATED ALWAYS.

因此,你不能意外地“忘记”序列的使用。你仍然可以强制这样做,使用 override system value选项:

insert into t2 (id) overriding system value values (1);

这样仍然会导致序列与表中的值不同步,但至少您意识到了这一点。


identity列还有另一个优点: 它们还可以最小化为允许插入而需要给角色的授权。

使用 serial列的表需要表 还有上的 INSERT 特权,使用 identity列的表不需要基础序列上的 USAGE 特权。授予 INSERT 特权就足够了。


建议 使用新的标识语法而不是系列标识语法