PostgreSQL AUTO INCREMENT(自動增長) 的使用
下面是一份 PostgreSQL 自動增長(AUTO INCREMENT) 的 完整實(shí)戰(zhàn)手冊,涵蓋 序列(SEQUENCE)、SERIAL、IDENTITY、自定義、并發(fā)安全、性能、遷移、常見陷阱與最佳實(shí)踐,適合開發(fā)、DBA、架構(gòu)師使用。
一、PostgreSQL 的自動增長機(jī)制
PostgreSQL 不使用 AUTO_INCREMENT 關(guān)鍵字(那是 MySQL 的寫法),而是使用 序列(SEQUENCE) + SERIAL / IDENTITY。
| 方式 | 說明 |
|---|---|
| SERIAL | 老版本兼容(內(nèi)部創(chuàng)建序列) |
| IDENTITY | SQL 標(biāo)準(zhǔn),推薦(PostgreSQL 10+) |
| SEQUENCE | 底層對象,可獨(dú)立管理 |
二、三種實(shí)現(xiàn)方式對比
| 方式 | 語法 | 是否標(biāo)準(zhǔn) | 是否可控 | 推薦 |
|---|---|---|---|---|
| SERIAL | id SERIAL | 否 | 一般 | 兼容舊項(xiàng)目 |
| BIGSERIAL | id BIGSERIAL | 否 | 一般 | 大數(shù)據(jù)量 |
| IDENTITY | id GENERATED ALWAYS AS IDENTITY | 是 | 高 | 強(qiáng)烈推薦 |
三、基本使用示例
1.SERIAL(傳統(tǒng)方式)
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
內(nèi)部自動創(chuàng)建: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 | 默認(rèn),禁止手動插入 |
| 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)底層原理
-- 查看自動創(chuàng)建的序列
SELECT pg_get_serial_sequence('users', 'id');
-- 返回: public.users_id_seq
-- 直接操作序列
SELECT nextval('users_id_seq'); -- 獲取下一個值
SELECT setval('users_id_seq', 100); -- 設(shè)置當(dāng)前值
SELECT currval('users_id_seq'); -- 獲取當(dāng)前值(事務(wù)內(nèi))
手動創(chuàng)建序列
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 詳細(xì)對比
| 特性 | SERIAL | IDENTITY |
|---|---|---|
| SQL 標(biāo)準(zhǔn) | 否 | 是 |
| 可顯式插入 | 允許 | ALWAYS 禁止,BY DEFAULT 允許 |
| 序列名固定 | 是(table_col_seq) | 是(系統(tǒng)命名) |
| 可重用序列 | 困難 | 容易 |
| 遷移兼容性 | 好 | 需 PostgreSQL 10+ |
| 推薦度 | 3 stars | 5 stars |
六、常見操作:重置、跳躍、修復(fù)
1. 重置 ID 從 1 開始
-- SERIAL 表
TRUNCATE TABLE users RESTART IDENTITY;
-- 或手動
SELECT setval(pg_get_serial_sequence('users', 'id'), 1, false);
2. 修復(fù) 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(預(yù)留)
SELECT setval('users_id_seq', 10000);
-- 下一個 INSERT 從 10001 開始
七、并發(fā)安全與性能
| 場景 | 行為 |
|---|---|
| 高并發(fā)插入 | 安全(序列是事務(wù)安全的) |
| 事務(wù)回滾 | ID 不回退(序列已分配) |
| 緩存(CACHE) | 提升性能,但回滾會造成空洞 |
-- 創(chuàng)建高性能序列 CREATE SEQUENCE fast_seq CACHE 100; -- 100 個值預(yù)分配,減少鎖競爭
空洞是正常現(xiàn)象,不要試圖消除
八、與外鍵、復(fù)制、遷移
1. 外鍵引用
CREATE TABLE orders (
id BIGSERIAL PRIMARY KEY,
user_id INT REFERENCES users(id)
);
-- 沒問題
2. 邏輯復(fù)制 / pg_dump
IDENTITY列會自動處理SERIAL需注意序列權(quán)限
-- 導(dǎo)出時包含序列 pg_dump -Fc -f backup.dump dbname
3. MySQL 遷移到 PostgreSQL
-- MySQL id INT AUTO_INCREMENT PRIMARY KEY -- 轉(zhuǎn)為 PostgreSQL id INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY
九、查看與管理序列
-- 查看所有序列
SELECT * FROM information_schema.sequences;
-- 查看系統(tǒng)序列
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 session | currval() 未調(diào)用 nextval() | 先 nextval() |
| ID 跳躍 | 事務(wù)回滾、CACHE | 正常現(xiàn)象 |
| 遷移后 ID 從 1 開始 | 未 RESTART IDENTITY | TRUNCATE ... RESTART IDENTITY |
| GENERATED ALWAYS 插入失敗 | 顯式插入 | 省略列或用 BY DEFAULT |
插入時覆蓋 IDENTITY(特殊場景)
INSERT INTO products(id, name) VALUES (999, 'Legacy Product') OVERRIDING SYSTEM VALUE;
十一、最佳實(shí)踐腳本
1. 標(biāo)準(zhǔn)建表模板(推薦)
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()
);
-- 觸發(fā)器自動更新 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. 安全插入(支持覆蓋)
-- 允許導(dǎo)入舊數(shù)據(jù) INSERT INTO customers(id, email, name) VALUES (1001, 'old@example.com', 'Legacy User') OVERRIDING SYSTEM VALUE;
3. 重置測試數(shù)據(jù)
TRUNCATE TABLE customers, orders, products RESTART IDENTITY CASCADE;
十二、性能優(yōu)化建議
| 建議 | 說明 |
|---|---|
| 用 BIGINT 而非 INT | 避免溢出 |
| 序列 CACHE 20~100 | 提升插入性能 |
| 分區(qū)表用獨(dú)立序列 | 避免熱點(diǎn) |
| 避免 SELECT currval() | 用 RETURNING id |
-- 插入并返回 ID(推薦)
INSERT INTO users(name) VALUES ('Tom')
RETURNING id;
十三、速查表
| 命令 | 用途 |
|---|---|
| SERIAL | 自動創(chuàng)建序列 |
| GENERATED ALWAYS AS IDENTITY | 標(biāo)準(zhǔn),禁止手動插入 |
| GENERATED BY DEFAULT AS IDENTITY | 允許手動插入 |
| nextval('seq') | 獲取下一個值 |
| setval('seq', n) | 設(shè)置當(dāng)前值 |
| TRUNCATE ... RESTART IDENTITY | 重置序列 |
| OVERRIDING SYSTEM VALUE | 插入時覆蓋 ID |
| RETURNING id | 獲取插入的 ID |
十四、決策樹

十五、常見面試題
| 問題 | 答案 |
|---|---|
| PostgreSQL 如何實(shí)現(xiàn)自增? | 使用 SEQUENCE |
| SERIAL 和 IDENTITY 區(qū)別? | IDENTITY 是標(biāo)準(zhǔn),SERIAL 是擴(kuò)展 |
| 事務(wù)回滾后 ID 會回退嗎? | 不會 |
| 如何插入指定 ID? | OVERRIDING SYSTEM VALUE |
| 如何查看當(dāng)前序列值? | SELECT last_value FROM seq_name |
十六、遷移對照表(MySQL → PostgreSQL)
| MySQL | PostgreSQL |
|---|---|
| AUTO_INCREMENT | GENERATED ALWAYS AS IDENTITY |
| INT AUTO_INCREMENT PRIMARY KEY | INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY |
| BIGINT AUTO_INCREMENT | BIGINT GENERATED ALWAYS AS IDENTITY |
| INSERT IGNORE | ON CONFLICT DO NOTHING |
到此這篇關(guān)于PostgreSQL AUTO INCREMENT(自動增長) 的使用的文章就介紹到這了,更多相關(guān)PostgreSQL AUTO INCREMENT內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Postgresql - 查看鎖表信息的實(shí)現(xiàn)
這篇文章主要介紹了Postgresql 查看鎖表信息的實(shí)現(xiàn),具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-12-12
postgresql數(shù)據(jù)庫連接數(shù)和狀態(tài)查詢操作
這篇文章主要介紹了postgresql數(shù)據(jù)庫連接數(shù)和狀態(tài)查詢操作,具有很好的參考價值,對大家有所幫助。一起跟隨小編過來看看吧2021-02-02
PostgreSQL連接數(shù)過多報(bào)錯:too many clients already的解決
在使用 Navicat 連接 PostgreSQL 數(shù)據(jù)庫時,突然遭遇到了一個報(bào)錯:“FATAL: sorry, too many clients already”,這一錯誤提示表明數(shù)據(jù)庫連接數(shù)已經(jīng)達(dá)到上限,無法再創(chuàng)建新連接,所以本文給大家介紹了相關(guān)的解決辦法,需要的朋友可以參考下2024-03-03
PostgreSQL容器磁盤I/O監(jiān)控與優(yōu)化指南
在數(shù)據(jù)庫運(yùn)維工作中,磁盤 I/O 性能直接影響著 PostgreSQL 的查詢響應(yīng)速度和事務(wù)處理能力,本文給大家介紹了PostgreSQL容器磁盤I/O監(jiān)控與優(yōu)化指南,需要的朋友可以參考下2025-05-05
PostgreSQL流復(fù)制參數(shù)max_wal_senders的用法說明
這篇文章主要介紹了PostgreSQL流復(fù)制參數(shù)max_wal_senders的用法說明,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-12-12
PostgreSQL如何查看數(shù)據(jù)庫及表中數(shù)據(jù)占用空間大小詳解
這篇文章主要介紹了PostgreSQL中用于查看數(shù)據(jù)庫和表空間大小的函數(shù),并提供了每個函數(shù)的詳細(xì)說明和應(yīng)用場景,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下2025-02-02
PostgreSQL 對IN,EXISTS,ANY/ALL,JOIN的sql優(yōu)化方案
這篇文章主要介紹了PostgreSQL 對IN,EXISTS,ANY/ALL,JOIN的sql優(yōu)化方案,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2021-01-01

