PostgreSQL AUTO INCREMENT(自动增长) 的使用

 更新时间:2025年11月06日 10:40:54   作者:yingjuxia.com  
本文主要介绍 PostgreSQL的自动增长机制,包括 SERIAL(传统方式)、IDENTITY(推荐标准)和 SEQUENCE(底层对象)三种实现,具有一定的参考价值,感兴趣的可以了解一下

下面是一份 PostgreSQL 自动增长(AUTO INCREMENT) 的 完整实战手册,涵盖 序列(SEQUENCE)、SERIAL、IDENTITY、自定义、并发安全、性能、迁移、常见陷阱与最佳实践,适合开发、DBA、架构师使用。

一、PostgreSQL 的自动增长机制

PostgreSQL 不使用 AUTO_INCREMENT 关键字(那是 MySQL 的写法),而是使用 序列(SEQUENCE) + SERIAL / IDENTITY。

方式说明
SERIAL老版本兼容(内部创建序列)
IDENTITYSQL 标准,推荐(PostgreSQL 10+)
SEQUENCE底层对象,可独立管理

二、三种实现方式对比

方式语法是否标准是否可控推荐
SERIALid SERIAL一般兼容旧项目
BIGSERIALid BIGSERIAL一般大数据量
IDENTITYid GENERATED ALWAYS AS IDENTITY强烈推荐

三、基本使用示例

1.SERIAL(传统方式)

CREATE TABLE users (
    id SERIAL PRIMARY KEY,
    name TEXT
);

-- 插入时自动增长
INSERT INTO users(name) VALUES ('Alice');
-- id = 1

INSERT INTO users(name) VALUES ('Bob');
-- id = 2

内部自动创建:users_id_seq

2.IDENTITY(推荐方式)

CREATE TABLE products (
    id INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
    name TEXT,
    price NUMERIC
);

-- 插入
INSERT INTO products(name, price) VALUES ('iPhone', 999);
-- id = 1

两种 IDENTITY 模式

模式说明
GENERATED ALWAYS默认,禁止手动插入
GENERATED BY DEFAULT允许手动插入(若不填则自动)
-- 允许手动指定 ID
CREATE TABLE logs (
    id BIGINT GENERATED BY DEFAULT AS IDENTITY,
    message TEXT
);

INSERT INTO logs(id, message) VALUES (100, 'Custom ID');

四、序列(SEQUENCE)底层原理

-- 查看自动创建的序列
SELECT pg_get_serial_sequence('users', 'id');
-- 返回: public.users_id_seq

-- 直接操作序列
SELECT nextval('users_id_seq');  -- 获取下一个值
SELECT setval('users_id_seq', 100);  -- 设置当前值
SELECT currval('users_id_seq');  -- 获取当前值(事务内)

手动创建序列

CREATE SEQUENCE my_seq
    START WITH 1000
    INCREMENT BY 1
    MINVALUE 1
    MAXVALUE 999999
    CACHE 10;

CREATE TABLE orders (
    id INT PRIMARY KEY DEFAULT nextval('my_seq'),
    total NUMERIC
);

五、IDENTITY vs SERIAL 详细对比

特性SERIALIDENTITY
SQL 标准
可显式插入允许ALWAYS 禁止,BY DEFAULT 允许
序列名固定是(table_col_seq)是(系统命名)
可重用序列困难容易
迁移兼容性需 PostgreSQL 10+
推荐度3 stars5 stars

六、常见操作:重置、跳跃、修复

1. 重置 ID 从 1 开始

-- SERIAL 表
TRUNCATE TABLE users RESTART IDENTITY;

-- 或手动
SELECT setval(pg_get_serial_sequence('users', 'id'), 1, false);

2. 修复 ID 空洞(不推荐频繁操作)

-- 重新编号(慎用!影响外键)
WITH ranked AS (
    SELECT id, row_number() OVER (ORDER BY id) AS rn
    FROM users
)
UPDATE users u
SET id = r.rn
FROM ranked r
WHERE u.id = r.id;

3. 跳过一段 ID(预留)

SELECT setval('users_id_seq', 10000);
-- 下一个 INSERT 从 10001 开始

七、并发安全与性能

场景行为
高并发插入安全(序列是事务安全的)
事务回滚ID 不回退(序列已分配)
缓存(CACHE)提升性能,但回滚会造成空洞
-- 创建高性能序列
CREATE SEQUENCE fast_seq CACHE 100;

-- 100 个值预分配,减少锁竞争

空洞是正常现象,不要试图消除

八、与外键、复制、迁移

1. 外键引用

CREATE TABLE orders (
    id BIGSERIAL PRIMARY KEY,
    user_id INT REFERENCES users(id)
);
-- 没问题

2. 逻辑复制 / pg_dump

  • IDENTITY 列会自动处理
  • SERIAL 需注意序列权限
-- 导出时包含序列
pg_dump -Fc -f backup.dump dbname

3. MySQL 迁移到 PostgreSQL

-- MySQL
id INT AUTO_INCREMENT PRIMARY KEY

-- 转为 PostgreSQL
id INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY

九、查看与管理序列

-- 查看所有序列
SELECT * FROM information_schema.sequences;

-- 查看系统序列
SELECT schemaname, sequencename, last_value
FROM pg_sequences;

-- 修改序列
ALTER SEQUENCE users_id_seq
    INCREMENT BY 2
    MINVALUE 1
    MAXVALUE 1000000
    RESTART WITH 1;

十、常见错误与避坑

错误原因解决
ERROR: duplicate key value violates unique constraint手动插入冲突用 BY DEFAULT 或 OVERRIDING SYSTEM VALUE
sequence is not yet defined in this sessioncurrval() 未调用 nextval()先 nextval()
ID 跳跃事务回滚、CACHE正常现象
迁移后 ID 从 1 开始未 RESTART IDENTITYTRUNCATE ... RESTART IDENTITY
GENERATED ALWAYS 插入失败显式插入省略列或用 BY DEFAULT

插入时覆盖 IDENTITY(特殊场景)

INSERT INTO products(id, name)
VALUES (999, 'Legacy Product')
OVERRIDING SYSTEM VALUE;

十一、最佳实践脚本

1. 标准建表模板(推荐)

CREATE TABLE customers (
    id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
    email VARCHAR(255) UNIQUE NOT NULL,
    name TEXT,
    created_at TIMESTAMP DEFAULT NOW(),
    updated_at TIMESTAMP DEFAULT NOW()
);

-- 触发器自动更新 updated_at
CREATE OR REPLACE FUNCTION update_timestamp()
RETURNS TRIGGER AS $$
BEGIN
    NEW.updated_at = NOW();
    RETURN NEW;
END;
$$ LANGUAGE plpgsql;

CREATE TRIGGER trg_customers_updated_at
    BEFORE UPDATE ON customers
    FOR EACH ROW
    EXECUTE FUNCTION update_timestamp();

2. 安全插入(支持覆盖)

-- 允许导入旧数据
INSERT INTO customers(id, email, name)
VALUES (1001, 'old@example.com', 'Legacy User')
OVERRIDING SYSTEM VALUE;

3. 重置测试数据

TRUNCATE TABLE customers, orders, products RESTART IDENTITY CASCADE;

十二、性能优化建议

建议说明
用 BIGINT 而非 INT避免溢出
序列 CACHE 20~100提升插入性能
分区表用独立序列避免热点
避免 SELECT currval()用 RETURNING id
-- 插入并返回 ID(推荐)
INSERT INTO users(name) VALUES ('Tom')
RETURNING id;

十三、速查表

命令用途
SERIAL自动创建序列
GENERATED ALWAYS AS IDENTITY标准,禁止手动插入
GENERATED BY DEFAULT AS IDENTITY允许手动插入
nextval('seq')获取下一个值
setval('seq', n)设置当前值
TRUNCATE ... RESTART IDENTITY重置序列
OVERRIDING SYSTEM VALUE插入时覆盖 ID
RETURNING id获取插入的 ID

十四、决策树

十五、常见面试题

问题答案
PostgreSQL 如何实现自增?使用 SEQUENCE
SERIAL 和 IDENTITY 区别?IDENTITY 是标准,SERIAL 是扩展
事务回滚后 ID 会回退吗?不会
如何插入指定 ID?OVERRIDING SYSTEM VALUE
如何查看当前序列值?SELECT last_value FROM seq_name

十六、迁移对照表(MySQL → PostgreSQL)

MySQLPostgreSQL
AUTO_INCREMENTGENERATED ALWAYS AS IDENTITY
INT AUTO_INCREMENT PRIMARY KEYINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY
BIGINT AUTO_INCREMENTBIGINT GENERATED ALWAYS AS IDENTITY
INSERT IGNOREON CONFLICT DO NOTHING

到此这篇关于PostgreSQL AUTO INCREMENT(自动增长) 的使用的文章就介绍到这了,更多相关PostgreSQL AUTO INCREMENT内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • postgresql 赋权语句 grant的正确使用说明

    postgresql 赋权语句 grant的正确使用说明

    这篇文章主要介绍了postgresql 赋权语句 grant的正确使用说明,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2021-01-01
  • PostgreSQL的日期时间差DATEDIFF实例详解

    PostgreSQL的日期时间差DATEDIFF实例详解

    PostgreSQL是一款简介而又性能强大的数据库应用程序,其在日期时间数据方面所支持的功能也都非常给力,下面这篇文章主要给大家介绍了关于PostgreSQL的日期时间差DATEDIFF的相关资料,需要的朋友可以参考下
    2023-04-04
  • 详解PostgreSQL 实现定时任务的 4 种方法

    详解PostgreSQL 实现定时任务的 4 种方法

    这篇文章主要介绍了PostgreSQL 实现定时任务的 4 种方法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-02-02
  • 解决postgresql无法远程访问的情况

    解决postgresql无法远程访问的情况

    这篇文章主要介绍了解决postgresql无法远程访问的情况,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2021-01-01
  • PostgreSQL流复制参数max_wal_senders的用法说明

    PostgreSQL流复制参数max_wal_senders的用法说明

    这篇文章主要介绍了PostgreSQL流复制参数max_wal_senders的用法说明,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-12-12
  • Postgresql数据库密码忘记的详细解决方法

    Postgresql数据库密码忘记的详细解决方法

    在使用PostgreSQL数据库时,忘记数据库密码可能会影响到正常的开发和维护工作,这篇文章主要介绍了Postgresql数据库密码忘记的详细解决方法,文中通过代码介绍的非常详细,需要的朋友可以参考下
    2025-06-06
  • 详解PostgreSQL 14.4安装使用及一些安装的异常问题

    详解PostgreSQL 14.4安装使用及一些安装的异常问题

    这篇文章主要介绍了PostgreSQL 14.4的安装以及使用以及一些安装的异常,本文通过图文并茂的形式给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-07-07
  • PostgreSQL无法查看表中数据问题的原因和解决方法

    PostgreSQL无法查看表中数据问题的原因和解决方法

    在 PostgreSQL 中,恢复数据库后,使用 DBeaver 等工具可以看到数据库和表名,但无法查询到表中数据,可能有很多原因,本文给大家分析了PostgreSQL无法查看表中数据问题的原因和解决方法,需要的朋友可以参考下
    2025-04-04
  • 查询PostgreSQL中所有表逻辑外键的方法

    查询PostgreSQL中所有表逻辑外键的方法

    本文介绍了如何查询PostgreSQL中所有表的逻辑外键,并指导您如何先删除再重新建立这些外键,本文通过示例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友一起看看吧
    2023-08-08
  • postgresql关于like%xxx%的优化操作

    postgresql关于like%xxx%的优化操作

    这篇文章主要介绍了postgresql关于like%xxx%的优化操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2021-01-01

最新评论