高斯数据库触发器实现流水号的
✅ 一、修改表结构:支持多业务类型
CREATE TABLE serial_number (biz_type TEXT NOT NULL,serial_date DATE NOT NULL,current_no INT NOT NULL,PRIMARY KEY (biz_type, serial_date)
);
✅ 二、生成函数:带业务前缀
CREATE OR REPLACE FUNCTION generate_serial_no(p_biz_type TEXT)
RETURNS TEXT AS $$
DECLAREtoday DATE := CURRENT_DATE;next_no INT;serial TEXT;
BEGIN-- 检查是否已有记录IF EXISTS (SELECT 1 FROM serial_numberWHERE biz_type = p_biz_type AND serial_date = today) THEN-- 更新序号UPDATE serial_numberSET current_no = current_no + 1WHERE biz_type = p_biz_type AND serial_date = todayRETURNING current_no INTO next_no;ELSE-- 插入新记录INSERT INTO serial_number(biz_type, serial_date, current_no)VALUES (p_biz_type, today, 1)RETURNING current_no INTO next_no;END IF;-- 拼接业务前缀 + 日期 + 三位序号serial := UPPER(p_biz_type) || TO_CHAR(today, 'YYYYMMDD') || LPAD(next_no::TEXT, 3, '0');RETURN serial;
END;
$$ LANGUAGE plpgsql;
✅ 三、使用示例
SELECT generate_serial_no('order');
-- 返回:ORDER20250725001SELECT generate_serial_no('invoice');
-- 返回:INVOICE20250725001
✅ 四、可选扩展(说明)
如果你还有这些需求,也可以加上:
扩展功能 | 说明 |
---|---|
自定义位数 | 把 LPAD(..., 3, '0') 改成 LPAD(..., n, '0') |
加密或混淆 | 可以在返回值中追加随机字母或哈希 |
使用事务封装 | 保证生成唯一性,在高并发时推荐加 FOR UPDATE |
触发器(Trigger)+ 触发器函数
你是想实现这样一种效果吧:
✅ 当你
INSERT
某张业务表(比如订单表)时,流水号字段自动生效,自动生成像ORDER20250726001
的编号,不需要你手动调用generate_serial_no()
。
可以!下面我教你通过 触发器(Trigger)+ 触发器函数 实现这个自动化。
✅ 一、业务表设计(例如订单表)
CREATE TABLE orders (id SERIAL PRIMARY KEY,order_no TEXT, -- 自动生成的流水号customer_name TEXT,create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
✅ 二、创建触发器函数:自动生成 order_no
CREATE OR REPLACE FUNCTION auto_generate_order_no()
RETURNS TRIGGER AS $$
BEGINIF NEW.order_no IS NULL THENNEW.order_no := generate_serial_no('order');END IF;RETURN NEW;
END;
$$ LANGUAGE plpgsql;
✅ 三、创建触发器
CREATE TRIGGER trg_orders_generate_no
BEFORE INSERT ON orders
FOR EACH ROW
EXECUTE FUNCTION auto_generate_order_no();
✅ 四、插入数据测试
INSERT INTO orders (customer_name) VALUES ('张三');
-- 自动生成 order_no,如:ORDER20250725001INSERT INTO orders (customer_name) VALUES ('李四');
-- 自动生成 order_no,如:ORDER20250725002
✅ 五、如果你有多个表共享流水号逻辑怎么办?
很好,这是实际开发中非常常见的需求。
你有多个业务表(如订单表、发票表、合同表等),每个表都要自动生成类似 ORDER20250726001
、INVOICE20250726001
的流水号,但又不想为每张表单独写一个触发器函数,那该怎么做?
✅ 目标
- 多个表插入时自动生成带前缀的流水号;
- 复用同一个触发器函数;
- 每张表生成自己的前缀流水号(如
orders
表前缀是ORDER
)。
✅ 一、准备工作:映射表名到前缀
我们先建一个映射表,配置表名 → 前缀:
CREATE TABLE biz_prefix_map (table_name TEXT PRIMARY KEY,prefix TEXT NOT NULL
);-- 示例数据
INSERT INTO biz_prefix_map (table_name, prefix) VALUES
('orders', 'ORDER'),
('invoices', 'INVOICE'),
('contracts', 'CONTRACT');
✅ 二、共用的触发器函数
这个函数可以被所有业务表共用,自动从映射表中获取前缀:
CREATE OR REPLACE FUNCTION auto_generate_serial_no()
RETURNS TRIGGER AS $$
DECLAREbiz_prefix TEXT;
BEGIN-- 获取当前触发表的业务前缀SELECT prefix INTO biz_prefixFROM biz_prefix_mapWHERE table_name = TG_TABLE_NAME;IF biz_prefix IS NULL THENRAISE EXCEPTION 'No prefix configured for table %', TG_TABLE_NAME;END IF;-- 设置流水号字段(字段名必须统一为 serial_no 或自己统一规则)IF NEW.serial_no IS NULL THENNEW.serial_no := generate_serial_no(biz_prefix);END IF;RETURN NEW;
END;
$$ LANGUAGE plpgsql;
✅ 三、你的业务表结构统一命名(字段统一为 serial_no
)
例如:
CREATE TABLE orders (id SERIAL PRIMARY KEY,serial_no TEXT, -- 自动生成的编号customer_name TEXT
);CREATE TABLE invoices (id SERIAL PRIMARY KEY,serial_no TEXT,amount NUMERIC
);
✅ 四、为每个表添加触发器(共用函数)
CREATE TRIGGER trg_orders_serial
BEFORE INSERT ON orders
FOR EACH ROW
EXECUTE FUNCTION auto_generate_serial_no();CREATE TRIGGER trg_invoices_serial
BEFORE INSERT ON invoices
FOR EACH ROW
EXECUTE FUNCTION auto_generate_serial_no();
✅ 五、插入效果
INSERT INTO orders (customer_name) VALUES ('小张');
-- 自动生成 serial_no:ORDER20250725001INSERT INTO invoices (amount) VALUES (300.00);
-- 自动生成 serial_no:INVOICE20250725001
✅ 总结
优点 | 说明 |
---|---|
统一管理 | 所有流水号逻辑集中在一张表和一个函数里 |
易扩展 | 新增业务表只需加一条映射数据和触发器 |
自动生效 | 所有业务表自动生成唯一编号 |