PostgreSQL 10 新特性 - identity column (serial, 自增)

本文涉及的产品
云原生数据库 PolarDB MySQL 版,Serverless 5000PCU 100GB
云原生数据库 PolarDB 分布式版,标准版 2核8GB
云数据库 RDS MySQL Serverless,0.5-2RCU 50GB
简介:

标签

PostgreSQL , 10 , 特性 , identify , 自增 , 覆盖 , SQL Server IDENTITY兼容 , SQL标准


背景

自增列是数据库的一个常用功能,PostgreSQL的自增列在10的版本出来前,有两种非常简单的方法来实现:

1、serial类型,自动创建一个序列,同时将列设置为INT,默认值设置为nextval('序列')。

create table test(id serial, info text);  
  
postgres=# \d+ test  
                                                Table "public.test"  
 Column |  Type   | Collation | Nullable |             Default              | Storage  | Stats target | Description   
--------+---------+-----------+----------+----------------------------------+----------+--------------+-------------  
 id     | integer |           | not null | nextval('test_id_seq'::regclass) | plain    |              |   
 info   | text    |           |          |                                  | extended |              |   

2、serial8类型,,自动创建一个序列,同时将列设置为INT8,默认值设置为nextval('序列')。

create table test(id serial8, info text);  

3、序列+默认值设置为序列,

create sequence seq1;  
  
create table test (id int default nextval('seq1'), info text);  

为了兼容SQL Server或SQL标准,PostgreSQL 10加入了IDENTITY列的支持。实际上功效类似,都是为了生成默认值。

但是IDENTITY加入了一个新的功能,可以允许用户选择是否覆盖这个列的默认值。

PostgreSQL IDENTITY列语法

1、创建IDENTITY列。

create table语法中,在列的类型后使用如下语法定义identity列。

ALWAYS,表示优先使用系统列生成的自增值。

BY DEFAULT,表示优先使用用户输入的值。

使用COPY导入数据时,输入的值会强行覆盖IDENTITY的设置。不管使用always还是by default。

GENERATED { ALWAYS | BY DEFAULT } AS IDENTITY [ ( sequence_options ) ]  
  
This clause creates the column as an identity column.   
  
It will have an implicit sequence attached to it and the column   
in new rows will automatically have values from the sequence assigned to it.  
  
The clauses ALWAYS and BY DEFAULT determine how the sequence   
value is given precedence over a user-specified value in an INSERT statement.   
  
If ALWAYS is specified, a user-specified value is only accepted if the   
INSERT statement specifies OVERRIDING SYSTEM VALUE.   
  
If BY DEFAULT is specified, then the user-specified value takes precedence.   
  
See INSERT for details. (In the COPY command, user-specified values are always used regardless of this setting.)  
  
The optional sequence_options clause can be used to override the options of the sequence.   
See CREATE SEQUENCE for details.  

例子

postgres=# create table test (id int GENERATED ALWAYS AS IDENTITY (cache 100), info text);  
CREATE TABLE  
  
postgres=# create table test1 (id int GENERATED BY DEFAULT AS IDENTITY (cache 100), info text);  
CREATE TABLE  
  
postgres=# \d test  
                          Table "public.test"  
 Column |  Type   | Collation | Nullable |           Default              
--------+---------+-----------+----------+------------------------------  
 id     | integer |           | not null | generated always as identity  
 info   | text    |           |          |   
  
postgres=# \d test1  
                            Table "public.test1"  
 Column |  Type   | Collation | Nullable |             Default                
--------+---------+-----------+----------+----------------------------------  
 id     | integer |           | not null | generated by default as identity  
 info   | text    |           |          |   

实际上identify列,也使用了序列,如下:

postgres=# \ds  
              List of relations  
 Schema |     Name     |   Type   |  Owner     
--------+--------------+----------+----------  
 public | test1_id_seq | sequence | postgres  
 public | test_id_seq  | sequence | postgres  
  
postgres=# drop sequence test1_id_seq;  
错误:  无法删除 序列 test1_id_seq, 因为 表 test1 字段 id 需要它  
HINT:  您也可以删除 表 test1 字段 id 代替.  

2、插入,如何覆盖默认值或覆盖用户提供值。

当identity列被定义为GENERATED ALWAYS AS IDENTITY时,如果要覆盖系统产生的值,需要使用OVERRIDING SYSTEM VALUE,否则会报错。

OVERRIDING SYSTEM VALUE  
  
Without this clause, it is an error to specify an explicit value   
(other than DEFAULT) for an identity column defined as GENERATED ALWAYS.   
  
This clause overrides that restriction.  

当identity列被定义为GENERATED BY DEFAULT AS IDENTITY时,如果要使用系统产生的值(即覆盖用户提交的值),需要使用OVERRIDING USER VALUE,否则会使用用户提交的值。

OVERRIDING USER VALUE  
  
If this clause is specified, then any values supplied for   
identity columns defined as GENERATED BY DEFAULT are ignored   
and the default sequence-generated values are applied.  
  
This clause is useful for example when copying values between tables.   
Writing INSERT INTO tbl2 OVERRIDING USER VALUE SELECT * FROM tbl1 will   
copy from tbl1 all columns that are not identity columns in tbl2   
while values for the identity columns in tbl2 will be generated by the   
sequences associated with tbl2.  

例子:

1、覆盖IDENTITY列,系统自动生成的自增值。

OVERRIDING SYSTEM VALUE

postgres=# insert into test (id, info) values (1,'test');  
错误:  cannot insert into column "id"  
DETAIL:  Column "id" is an identity column defined as GENERATED ALWAYS.  
HINT:  Use OVERRIDING SYSTEM VALUE to override.  
  
postgres=# insert into test (id, info) OVERRIDING SYSTEM VALUE values (1,'test');  
INSERT 0 1  
  
postgres=# select * from test;  
 id | info   
----+------  
  1 | test  
(1 row)  

2、覆盖用户提供的值。

postgres=# insert into test1 values (1,'test');  -- 用户输入的值优先  
INSERT 0 1  
postgres=# insert into test1 (id, info) OVERRIDING user VALUE values (1000,'test');  -- 覆盖用户输入的值(使用系统列定义的自增值)  
INSERT 0 1  
postgres=# select * from test1;  
 id | info   
----+------  
  1 | test  
  1 | test  
(2 rows)  

3、COPY,不管always还是by default,总是使用用户提供的值。

postgres=# copy test from stdin  
postgres-# ;  
Enter data to be copied followed by a newline.  
End with a backslash and a period on a line by itself, or an EOF signal.  
>> 1999 abc  
>> 2999 cde      
>> \.  
COPY 2  
postgres=# select * from test;  
  id  | info   
------+------  
    1 | test  
 1999 | abc  
 2999 | cde  
(3 rows)  

小结

现在你应该知道,在PostgreSQL中有几种定义自增列的方法了吧。

1、serial或serial8类型。

2、identity列定义。

参考

https://www.postgresql.org/docs/10/static/sql-createtable.html

https://www.postgresql.org/docs/10/static/sql-insert.html

https://www.postgresql.org/docs/10/static/sql-createsequence.html

相关实践学习
使用PolarDB和ECS搭建门户网站
本场景主要介绍基于PolarDB和ECS实现搭建门户网站。
阿里云数据库产品家族及特性
阿里云智能数据库产品团队一直致力于不断健全产品体系,提升产品性能,打磨产品功能,从而帮助客户实现更加极致的弹性能力、具备更强的扩展能力、并利用云设施进一步降低企业成本。以云原生+分布式为核心技术抓手,打造以自研的在线事务型(OLTP)数据库Polar DB和在线分析型(OLAP)数据库Analytic DB为代表的新一代企业级云原生数据库产品体系, 结合NoSQL数据库、数据库生态工具、云原生智能化数据库管控平台,为阿里巴巴经济体以及各个行业的企业客户和开发者提供从公共云到混合云再到私有云的完整解决方案,提供基于云基础设施进行数据从处理、到存储、再到计算与分析的一体化解决方案。本节课带你了解阿里云数据库产品家族及特性。
相关文章
|
SQL 关系型数据库 OLAP
|
10月前
|
存储 关系型数据库 数据库
探索PostgreSQL 14新特性--SEARCH和CYCLE
探索PostgreSQL 14新特性--SEARCH和CYCLE
51 0
|
10月前
|
存储 缓存 关系型数据库
PostgreSQL 14新特性--减少索引膨胀
PostgreSQL 14新特性--减少索引膨胀
399 0
|
SQL 存储 缓存
从研发角度深入了解RDS AliSQL内核2020新特性
内容简要: 一、关于内核 二、内核特性详解 一、 关于内核 (一)回归内核
从研发角度深入了解RDS AliSQL内核2020新特性
|
SQL 存储 缓存
从研发角度深入了解RDS AliSQL内核2020新特性 ——楼方鑫(黄忠)
从研发角度深入了解RDS AliSQL内核2020新特性 ——楼方鑫(黄忠)
从研发角度深入了解RDS AliSQL内核2020新特性    ——楼方鑫(黄忠)
|
SQL AliSQL Cloud Native
RDS发布会解读 | AliSQL内核新特性
AliSQL在2020年做了不少事情,有必要总结分享一下,以便让大家更好地知道有哪些特性,可以在哪些业务场景中使用到,也是为了在2021年更好地向前发展。
438 0
RDS发布会解读 | AliSQL内核新特性
|
SQL AliSQL Cloud Native
RDS发布会解读| AliSQL内核新特性
AliSQL在2020年做了不少事情,有必要总结分享一下,以便让大家更好地知道有哪些特性,可以在哪些业务场景中使用到,也是为了在2021年更好的向前发展。在年初时计划的一些企业级功能基本上都实现了,并且在过程中特别强调了功能的场景通用性,不再是从某个行业某个特定业务或应用场景设计(比如电商秒杀),而是从云上众多用户的不同场景出发,并且不需要用户应用或SQL改造配合(直接一个开关就可以开启的),还要求在RDS 56/57/80三个主流版本上都有同样的体验,从云场景而生并为云场景服务的技术,都是云原生技术。这一目标角度的调整的确是给自己加了不少难度,但研发让所有云上用户都能轻松受益享受技术红利的新
2464 0
RDS发布会解读| AliSQL内核新特性
|
SQL 存储 Oracle
PostgreSQL Oracle 兼容性 - Oracle 19c 新特性在PostgreSQL中的使用
PostgreSQL Oracle 兼容性 - Oracle 19c 新特性在PostgreSQL中的使用
2807 0
|
SQL 存储 Oracle
PostgreSQL Oracle 兼容性 - Oracle 19c 新特性在PostgreSQL中的使用
标签 PostgreSQL , Oracle 兼容性 , Oracle 19c 背景 《PostgreSQL 覆盖 Oracle 18c 重大新特性》 Oracle 19c 新特性摘自盖老师《Oracle 19c 新特性及官方文档抢鲜下载》文章,其中有一些特性在PostgreSQL中很早以前已经支持。本文旨在介绍PG如何使用这些特性。 1.Data Guard 备库DML自动重定向
679 0
|
数据格式 JSON 索引
AnalyticDB for PostgreSQL 6.0新特性 JSONB数据类型
ADB PG 6.0 JSONB数据类型特性 JSON Types JSON数据类型顾名思义是用来存储JSON数据的,这种数据也可以用text类型来存储,但是JSON数据类型会对数据做JSON规则校验,同时提供一些列的特定的JSON化的函数,让用户可以对这些数据作出一些特殊的操作。
2799 0

相关产品

  • 云原生数据库 PolarDB