如何在 Postgres 中创建相当于 SQL 服务器的标识列
How to create the equivalent of an SQL Server's identity column in Postgres
有一个应用程序使用 MSSQL 作为其后端。现在我正在开发代码,以便它可以使用 PostgreSQL。除了执行时有一点不同外,我几乎完成了它:
保存新应用程序时,
SQL 服务器代码:
create table tower
(
npages integer,
ifnds integer,
ifnid integer,
name varchar(20),
towid integer not null IDENTITY
)
PostgreSQL 代码:
create table tower
(
npages integer,
ifnds integer,
ifnid integer,
name varchar(20)
)
为什么在通过 PostgreSQL 执行时不会自动生成 towid 字段(默认字段)?
有什么可能的原因吗?触发器?程序?
PostgreSQL 将完全按照您的要求创建 table。它不会自动生成一些列(几乎,但这是低级的)。您需要在请求中添加 towid serial primary key
。
tl;博士
现在在 Postgres 10 中,根据 SQL 标准指定 GENERATED BY DEFAULT AS IDENTITY
。
create table tower
(
npages integer,
ifnds integer,
ifnid integer,
name varchar(20),
towid integer GENERATED BY DEFAULT AS IDENTITY -- per SQL standard
)
标识列
Postgres 10 现在支持 identity column 的概念,并使用标准的 SQL 语法。虽然我不是 MS SQL 服务器方面的专家,但我相信这个新标准支持是等效的。
GENERATED … AS IDENTITY
在 CREATE TABLE
期间使用的 GENERATED … AS IDENTITY
命令创建了一个隐式序列。与 SERIAL
不同,该序列的创建、命名、权限和删除对您来说都是透明的。现在非常直观。如果您授予 table 使用权限,他们将获得序列的权限。如果删除 table,序列将自动删除。
两种标准语法。仅当您传递一个值而不是让一个值生成时,差异才有意义。通常,人们总是依赖于生成的值,所以通常你会简单地使用第一个版本,GENERATED BY DEFAULT AS IDENTITY
.
GENERATED BY DEFAULT AS IDENTITY
- 生成一个值,除非
INSERT
命令提供一个值。
GENERATED ALWAYS AS IDENTITY
- 忽略
INSERT
提供的任何值,除非指定 OVERRIDING SYSTEM VALUE
有关文档,请参阅 CREATE TABLE
页面。
阅读 Peter Eisentraut 的 this interesting page。他用 SERIAL
解释了一些奇怪的问题。新的标识列功能没有此类问题。所以没有理由再使用 SERIAL
,没有缺点,只有优点; SERIAL
被 GENERATED … AS IDENTITY
取代。
请注意,标识列不一定是主键,也不会自动建立索引。因此,如果这是您的意图,您仍然需要明确指定 PRIMARY KEY
(通常是这种情况)。
CREATE TABLE person_ (
id_
INTEGER
GENERATED BY DEFAULT AS IDENTITY -- Replaces SERIAL. Implicitly creates a SEQUENCE, specified as DEFAULT.
PRIMARY KEY -- Creates index. Specifies UNIQUE. Marks column for relationships.
,
name_
VARCHAR( 80 )
) ;
目的是向您隐藏内部实施细节。您无需知道在幕后生成的序列的名称。例如,您可以在不知道底层顺序的情况下通过列重置计数器。
ALTER TABLE person_
ALTER COLUMN id_
RESTART WITH 1000 -- Reset sequence implicitly, without a name.
;
隐式指定身份:
- 标记列
NOT NULL
- 创建一个序列
- 序列类型与列匹配(32 位 64 位等)
- 将序列与列联系起来
- 继承权限
- 级联下降
- 即使列已重命名,仍与该列相关联
- 将序列指定为该列的默认值来源
身份列可以采用与CREATE SEQUENCE
相同的选项:
START WITH start
MINVALUE minvalue
| NO MINVALUE
MAXVALUE maxvalue
| NO MAXVALUE
INCREMENT [ BY ] increment
CYCLE
| NO CYCLE
CACHE
缓存
OWNED BY NONE
(为标识列指定所有权对我来说毫无意义,因为所有权是自动管理的)
愚蠢的选项示例:
id_ INTEGER
GENERATED BY DEFAULT AS IDENTITY (
START WITH 200
MINVALUE 100
MAXVALUE 205
CYCLE
INCREMENT BY 3
) PRIMARY KEY
添加 4 行:
200
203
100
103
有一个应用程序使用 MSSQL 作为其后端。现在我正在开发代码,以便它可以使用 PostgreSQL。除了执行时有一点不同外,我几乎完成了它:
保存新应用程序时,
SQL 服务器代码:
create table tower
(
npages integer,
ifnds integer,
ifnid integer,
name varchar(20),
towid integer not null IDENTITY
)
PostgreSQL 代码:
create table tower
(
npages integer,
ifnds integer,
ifnid integer,
name varchar(20)
)
为什么在通过 PostgreSQL 执行时不会自动生成 towid 字段(默认字段)?
有什么可能的原因吗?触发器?程序?
PostgreSQL 将完全按照您的要求创建 table。它不会自动生成一些列(几乎,但这是低级的)。您需要在请求中添加 towid serial primary key
。
tl;博士
现在在 Postgres 10 中,根据 SQL 标准指定 GENERATED BY DEFAULT AS IDENTITY
。
create table tower
(
npages integer,
ifnds integer,
ifnid integer,
name varchar(20),
towid integer GENERATED BY DEFAULT AS IDENTITY -- per SQL standard
)
标识列
Postgres 10 现在支持 identity column 的概念,并使用标准的 SQL 语法。虽然我不是 MS SQL 服务器方面的专家,但我相信这个新标准支持是等效的。
GENERATED … AS IDENTITY
在 CREATE TABLE
期间使用的 GENERATED … AS IDENTITY
命令创建了一个隐式序列。与 SERIAL
不同,该序列的创建、命名、权限和删除对您来说都是透明的。现在非常直观。如果您授予 table 使用权限,他们将获得序列的权限。如果删除 table,序列将自动删除。
两种标准语法。仅当您传递一个值而不是让一个值生成时,差异才有意义。通常,人们总是依赖于生成的值,所以通常你会简单地使用第一个版本,GENERATED BY DEFAULT AS IDENTITY
.
GENERATED BY DEFAULT AS IDENTITY
- 生成一个值,除非
INSERT
命令提供一个值。
- 生成一个值,除非
GENERATED ALWAYS AS IDENTITY
- 忽略
INSERT
提供的任何值,除非指定OVERRIDING SYSTEM VALUE
- 忽略
有关文档,请参阅 CREATE TABLE
页面。
阅读 Peter Eisentraut 的 this interesting page。他用 SERIAL
解释了一些奇怪的问题。新的标识列功能没有此类问题。所以没有理由再使用 SERIAL
,没有缺点,只有优点; SERIAL
被 GENERATED … AS IDENTITY
取代。
请注意,标识列不一定是主键,也不会自动建立索引。因此,如果这是您的意图,您仍然需要明确指定 PRIMARY KEY
(通常是这种情况)。
CREATE TABLE person_ (
id_
INTEGER
GENERATED BY DEFAULT AS IDENTITY -- Replaces SERIAL. Implicitly creates a SEQUENCE, specified as DEFAULT.
PRIMARY KEY -- Creates index. Specifies UNIQUE. Marks column for relationships.
,
name_
VARCHAR( 80 )
) ;
目的是向您隐藏内部实施细节。您无需知道在幕后生成的序列的名称。例如,您可以在不知道底层顺序的情况下通过列重置计数器。
ALTER TABLE person_
ALTER COLUMN id_
RESTART WITH 1000 -- Reset sequence implicitly, without a name.
;
隐式指定身份:
- 标记列
NOT NULL
- 创建一个序列
- 序列类型与列匹配(32 位 64 位等)
- 将序列与列联系起来
- 继承权限
- 级联下降
- 即使列已重命名,仍与该列相关联
- 将序列指定为该列的默认值来源
身份列可以采用与CREATE SEQUENCE
相同的选项:
START WITH start
MINVALUE minvalue
|NO MINVALUE
MAXVALUE maxvalue
|NO MAXVALUE
INCREMENT [ BY ] increment
CYCLE
|NO CYCLE
CACHE
缓存OWNED BY NONE
(为标识列指定所有权对我来说毫无意义,因为所有权是自动管理的)
愚蠢的选项示例:
id_ INTEGER
GENERATED BY DEFAULT AS IDENTITY (
START WITH 200
MINVALUE 100
MAXVALUE 205
CYCLE
INCREMENT BY 3
) PRIMARY KEY
添加 4 行:
200
203
100
103