PostgreSQL AUTO INCREMENT(自動增長) 的使用
下面是一份 PostgreSQL 自動增長(AUTO INCREMENT) 的 完整實戰(zhàn)手冊,涵蓋 序列(SEQUENCE)、SERIAL、IDENTITY、自定義、并發(fā)安全、性能、遷移、常見陷阱與最佳實踐,適合開發(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 | 底層對象,可獨立管理 |
二、三種實現(xiàn)方式對比
| 方式 | 語法 | 是否標(biāo)準(zhǔn) | 是否可控 | 推薦 |
|---|---|---|---|---|
| SERIAL | id SERIAL | 否 | 一般 | 兼容舊項目 |
| 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ù)分配,減少鎖競爭
空洞是正?,F(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 | 正?,F(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;
十一、最佳實踐腳本
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ū)表用獨立序列 | 避免熱點 |
| 避免 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 如何實現(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 賦權(quán)語句 grant的正確使用說明
這篇文章主要介紹了postgresql 賦權(quán)語句 grant的正確使用說明,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2021-01-01
詳解PostgreSQL 實現(xiàn)定時任務(wù)的 4 種方法
這篇文章主要介紹了PostgreSQL 實現(xiàn)定時任務(wù)的 4 種方法,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2021-02-02
PostgreSQL流復(fù)制參數(shù)max_wal_senders的用法說明
這篇文章主要介紹了PostgreSQL流復(fù)制參數(shù)max_wal_senders的用法說明,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-12-12
Postgresql數(shù)據(jù)庫密碼忘記的詳細(xì)解決方法
在使用PostgreSQL數(shù)據(jù)庫時,忘記數(shù)據(jù)庫密碼可能會影響到正常的開發(fā)和維護(hù)工作,這篇文章主要介紹了Postgresql數(shù)據(jù)庫密碼忘記的詳細(xì)解決方法,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下2025-06-06
詳解PostgreSQL?14.4安裝使用及一些安裝的異常問題
這篇文章主要介紹了PostgreSQL?14.4的安裝以及使用以及一些安裝的異常,本文通過圖文并茂的形式給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2022-07-07
PostgreSQL無法查看表中數(shù)據(jù)問題的原因和解決方法
在 PostgreSQL 中,恢復(fù)數(shù)據(jù)庫后,使用 DBeaver 等工具可以看到數(shù)據(jù)庫和表名,但無法查詢到表中數(shù)據(jù),可能有很多原因,本文給大家分析了PostgreSQL無法查看表中數(shù)據(jù)問題的原因和解決方法,需要的朋友可以參考下2025-04-04
postgresql關(guān)于like%xxx%的優(yōu)化操作
這篇文章主要介紹了postgresql關(guān)于like%xxx%的優(yōu)化操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2021-01-01

