# PostgreSQL SEQUENCE(序列)详解 ## 语句解析 ```sql DROP SEQUENCE IF EXISTS "public"."adm_encounter_id_seq"; CREATE SEQUENCE "public"."adm_encounter_id_seq" INCREMENT 1 MINVALUE 1 MAXVALUE 99999999 START 200 CACHE 1; ``` ## 逐行解释 ### 1. `DROP SEQUENCE IF EXISTS "public"."adm_encounter_id_seq";` - **作用**:如果序列已存在,先删除它 - **`IF EXISTS`**:如果序列不存在,不会报错,直接跳过 - **`"public"."adm_encounter_id_seq"`**:序列的完整名称 - `public`:模式(schema)名,默认模式 - `adm_encounter_id_seq`:序列名称 ### 2. `CREATE SEQUENCE "public"."adm_encounter_id_seq"` - **作用**:创建一个新的序列 - **序列名称**:`adm_encounter_id_seq`(用于 `adm_encounter` 表的主键自增) ### 3. `INCREMENT 1` - **作用**:每次递增的步长 - **含义**:每次调用 `nextval()` 时,序列值增加 1 - **示例**:如果当前值是 200,下次调用 `nextval()` 返回 201 ### 4. `MINVALUE 1` - **作用**:序列的最小值 - **含义**:序列值不能小于 1 - **注意**:如果序列达到最小值后继续递减,会报错(除非设置了 `CYCLE`) ### 5. `MAXVALUE 99999999` - **作用**:序列的最大值 - **含义**:序列值不能超过 99999999(8位数) - **注意**:如果序列达到最大值后继续递增,会报错(除非设置了 `CYCLE`) ### 6. `START 200` - **作用**:序列的起始值 - **含义**:序列从 200 开始 - **示例**:第一次调用 `nextval()` 返回 200,第二次返回 201,以此类推 ### 7. `CACHE 1` - **作用**:缓存大小 - **含义**:每次从数据库获取序列值时,预分配 1 个值到内存 - **说明**: - `CACHE 1`:每次只缓存 1 个值(最安全,但性能较低) - `CACHE 20`:每次缓存 20 个值(性能更好,但可能跳号) - **注意**:如果数据库重启,缓存中未使用的序列值会丢失,导致跳号 ## 使用示例 ### 1. 在表定义中使用(自动自增) ```sql CREATE TABLE "adm_encounter" ( "id" int8 NOT NULL DEFAULT nextval('adm_encounter_id_seq'::regclass), ... ); ``` ### 2. 手动获取下一个值 ```sql -- 获取下一个序列值 SELECT nextval('adm_encounter_id_seq'); -- 返回:200(第一次调用) SELECT nextval('adm_encounter_id_seq'); -- 返回:201(第二次调用) ``` ### 3. 查看当前值(不递增) ```sql SELECT currval('adm_encounter_id_seq'); -- 返回:当前序列值(不会增加) ``` ### 4. 重置序列 ```sql -- 将序列重置为指定值 SELECT setval('adm_encounter_id_seq', 200); ``` ## 实际应用场景 ### 场景1:插入数据时自动生成ID ```sql INSERT INTO adm_encounter (patient_id, organization_id, ...) VALUES (123, 456, ...); -- id 字段会自动使用序列的下一个值(如 200, 201, 202...) ``` ### 场景2:手动指定ID(不推荐) ```sql INSERT INTO adm_encounter (id, patient_id, ...) VALUES (999, 123, ...); -- 注意:如果手动插入的ID与序列值冲突,可能导致问题 ``` ## 注意事项 ### 1. 序列与雪花算法的区别 - **序列**:简单的数字递增(1, 2, 3...) - **雪花算法**:分布式ID生成算法(如:1996923066055286785) - **当前项目**:虽然定义了序列,但实际使用的是雪花算法(`IdType.ASSIGN_ID`) ### 2. 序列跳号的原因 - 事务回滚:如果事务回滚,序列值不会回退 - 缓存:`CACHE > 1` 时,数据库重启可能导致跳号 - 手动插入:手动插入ID后,序列不会自动调整 ### 3. 序列的优缺点 **优点**: - 简单易用 - 性能好(预分配) - 保证唯一性 **缺点**: - 可能跳号 - 不适合分布式环境 - 最大值有限制 ## 相关查询语句 ### 查看序列信息 ```sql -- 查看序列的详细信息 SELECT sequence_name AS 序列名称, last_value AS 当前值, start_value AS 起始值, increment_by AS 递增步长, max_value AS 最大值, min_value AS 最小值, cache_size AS 缓存大小 FROM information_schema.sequences WHERE sequence_name = 'adm_encounter_id_seq'; ``` ### 查看序列的下一个值(不实际使用) ```sql SELECT last_value, is_called FROM adm_encounter_id_seq; ``` ### 修改序列 ```sql -- 修改序列的起始值 ALTER SEQUENCE adm_encounter_id_seq RESTART WITH 1000; -- 修改序列的最大值 ALTER SEQUENCE adm_encounter_id_seq MAXVALUE 999999999; -- 修改序列的缓存大小 ALTER SEQUENCE adm_encounter_id_seq CACHE 20; ```