You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PostgreSQL实现不同用户独立递增ID的最优方案

需求背景

我有一个数据库,其中包含存储用户信息的members表,结构如下:

idemailpassword
1email@email.comrow
2email2@email.comrow

另有一个存储帖子信息的posts表,当前结构如下:

idmember_idcontent
11Hello World 1
21Hello World 2
32Word hello 1
42Word hello 2

我希望实现每个用户拥有独立的ID计数器,效果如下(每个用户的帖子ID从1开始递增):

idmember_idcontent
11Hello World
21Hello World
12Word hello
22Word hello

或者采用新增全局唯一main_id的结构:

main_ididmember_idcontent
111Hello World
221Hello World
312Word hello
422Word hello

我知道可以将id和member_id组合成唯一键,但这样无法使用自动递增计数器,需要在后端通过逻辑计算新ID。我想知道是否可以让PostgreSQL自动处理:传入member_id时,自动为该用户分配下一个可用的递增ID,就像普通计数器一样,是否可行?


解决方案

完全可以实现,推荐使用触发器+用户计数器表的方案,让PostgreSQL自动维护每个用户的独立ID递增逻辑,无需后端额外计算:

步骤1:创建用户帖子计数器表

专门记录每个用户的下一个可用帖子ID,确保原子性:

CREATE TABLE member_post_counters (
    member_id INT PRIMARY KEY REFERENCES members(id),
    next_post_id INT DEFAULT 1
);

步骤2:初始化现有用户的计数器

为已存在的用户初始化起始ID:

INSERT INTO member_post_counters (member_id)
SELECT id FROM members;

步骤3:编写生成下一个帖子ID的函数

实现原子性的ID递增逻辑,同时兼容新用户的自动初始化:

CREATE OR REPLACE FUNCTION get_next_post_id(p_member_id INT)
RETURNS INT AS $$
DECLARE
    next_id INT;
BEGIN
    -- 原子更新并获取当前可用ID
    UPDATE member_post_counters
    SET next_post_id = next_post_id + 1
    WHERE member_id = p_member_id
    RETURNING next_post_id - 1 INTO next_id;
    
    -- 若用户不存在(新用户),自动初始化计数器并返回1
    IF next_id IS NULL THEN
        INSERT INTO member_post_counters (member_id) VALUES (p_member_id)
        RETURNING next_post_id - 1 INTO next_id;
    END IF;
    
    RETURN next_id;
END;
$$ LANGUAGE plpgsql VOLATILE;

步骤4:修改posts表结构

根据你选择的结构二选一:

结构一(无全局main_id)

ALTER TABLE posts
DROP COLUMN id,
ADD COLUMN id INT,
ADD CONSTRAINT unique_member_post_id UNIQUE (member_id, id);

结构二(带全局唯一main_id)

ALTER TABLE posts
DROP COLUMN id,
ADD COLUMN id INT,
ADD COLUMN main_id SERIAL PRIMARY KEY,
ADD CONSTRAINT unique_member_post_id UNIQUE (member_id, id);

步骤5:创建触发自动赋值的触发器

让插入操作自动调用函数生成用户专属ID:

CREATE OR REPLACE FUNCTION set_post_id()
RETURNS TRIGGER AS $$
BEGIN
    NEW.id = get_next_post_id(NEW.member_id);
    RETURN NEW;
END;
$$ LANGUAGE plpgsql;

CREATE TRIGGER trigger_set_post_id
BEFORE INSERT ON posts
FOR EACH ROW EXECUTE FUNCTION set_post_id();

使用示例

插入帖子时只需传入member_id和content,PostgreSQL会自动分配用户专属的递增ID:

INSERT INTO posts (member_id, content) VALUES (1, 'Hello New Post');
INSERT INTO posts (member_id, content) VALUES (2, 'Hello New Post');

内容的提问来源于stack exchange,提问作者Lwyrn

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.23 18:53:12