Oracle序列与同义词 #
一、序列概述 #
1.1 什么是序列 #
序列(Sequence)是Oracle数据库中用于生成唯一数字的数据库对象。序列通常用于生成表的主键值,可以自动递增或递减。
text
序列特点
├── 自动生成唯一数字
├── 独立于表存在
├── 可被多个表共享
├── 支持递增和递减
└── 高效并发访问
1.2 序列应用场景 #
text
序列应用场景
├── 主键生成
│ └── 自动生成唯一ID
├── 订单编号
│ └── 生成连续订单号
├── 流水号
│ └── 生成业务流水号
└── 批次号
└── 生成批次标识
二、创建序列 #
2.1 基本语法 #
sql
-- 创建序列基本语法
CREATE SEQUENCE sequence_name
[INCREMENT BY n] -- 增量,默认1
[START WITH n] -- 起始值,默认1
[MAXVALUE n | NOMAXVALUE] -- 最大值
[MINVALUE n | NOMINVALUE] -- 最小值
[CYCLE | NOCYCLE] -- 是否循环
[CACHE n | NOCACHE] -- 缓存数量
[ORDER | NOORDER]; -- 是否保证顺序
2.2 创建简单序列 #
sql
-- 创建简单序列
CREATE SEQUENCE seq_employee_id;
-- 使用默认值:
-- INCREMENT BY 1
-- START WITH 1
-- NOMAXVALUE
-- NOMINVALUE
-- NOCYCLE
-- CACHE 20
-- NOORDER
-- 创建指定参数的序列
CREATE SEQUENCE seq_order_id
INCREMENT BY 1
START WITH 1000
MAXVALUE 999999999
NOCYCLE
CACHE 20;
-- 创建递减序列
CREATE SEQUENCE seq_decrement
INCREMENT BY -1
START WITH 100
MINVALUE 1
MAXVALUE 100
CYCLE;
2.3 序列参数详解 #
sql
-- INCREMENT BY:增量
-- 正数:递增序列
-- 负数:递减序列
CREATE SEQUENCE seq_increment_5
INCREMENT BY 5
START WITH 0; -- 0, 5, 10, 15, ...
-- START WITH:起始值
CREATE SEQUENCE seq_start_1000
START WITH 1000; -- 从1000开始
-- MAXVALUE/MINVALUE:最大/最小值
CREATE SEQUENCE seq_bounded
START WITH 1
INCREMENT BY 1
MAXVALUE 1000
MINVALUE 1;
-- CYCLE/NOCYCLE:循环
CREATE SEQUENCE seq_cycle
START WITH 1
MAXVALUE 10
CYCLE; -- 1,2,3,...,10,1,2,3,...
-- CACHE/NOCACHE:缓存
-- CACHE:预分配到内存,提高性能
-- NOCACHE:每次访问都更新序列
CREATE SEQUENCE seq_cache
CACHE 100; -- 缓存100个值
CREATE SEQUENCE seq_nocache
NOCACHE; -- 不缓存
-- ORDER/NOORDER:顺序保证
-- ORDER:保证按请求顺序生成
-- NOORDER:不保证顺序(默认)
CREATE SEQUENCE seq_order
ORDER; -- RAC环境需要
2.4 创建序列最佳实践 #
sql
-- 主键序列
CREATE SEQUENCE seq_employee_id
INCREMENT BY 1
START WITH 1
NOCACHE
NOCYCLE;
-- 订单号序列
CREATE SEQUENCE seq_order_no
INCREMENT BY 1
START WITH 100000
CACHE 100
NOCYCLE;
-- 高性能序列(允许跳号)
CREATE SEQUENCE seq_high_perf
INCREMENT BY 1
START WITH 1
CACHE 1000
NOORDER;
三、使用序列 #
3.1 序列伪列 #
sql
-- NEXTVAL:获取下一个值
SELECT seq_employee_id.NEXTVAL FROM DUAL;
-- CURRVAL:获取当前值(必须先调用NEXTVAL)
SELECT seq_employee_id.CURRVAL FROM DUAL;
-- 使用示例
-- 第一次调用NEXTVAL
SELECT seq_employee_id.NEXTVAL FROM DUAL; -- 返回1
-- 调用CURRVAL获取当前值
SELECT seq_employee_id.CURRVAL FROM DUAL; -- 返回1
-- 再次调用NEXTVAL
SELECT seq_employee_id.NEXTVAL FROM DUAL; -- 返回2
3.2 在INSERT中使用 #
sql
-- 插入数据时使用序列
INSERT INTO employees (employee_id, first_name, last_name)
VALUES (seq_employee_id.NEXTVAL, 'John', 'Doe');
-- 批量插入
INSERT ALL
INTO employees (employee_id, first_name) VALUES (seq_employee_id.NEXTVAL, 'John')
INTO employees (employee_id, first_name) VALUES (seq_employee_id.NEXTVAL, 'Jane')
INTO employees (employee_id, first_name) VALUES (seq_employee_id.NEXTVAL, 'Bob')
SELECT * FROM DUAL;
-- 使用子查询
INSERT INTO employees (employee_id, first_name, last_name)
SELECT seq_employee_id.NEXTVAL, first_name, last_name
FROM temp_employees;
3.3 在PL/SQL中使用 #
sql
-- PL/SQL中使用序列
DECLARE
v_employee_id NUMBER;
BEGIN
-- 获取下一个值
v_employee_id := seq_employee_id.NEXTVAL;
-- 插入数据
INSERT INTO employees (employee_id, first_name, last_name)
VALUES (v_employee_id, 'John', 'Doe');
-- 获取当前值
DBMS_OUTPUT.PUT_LINE('Current ID: ' || seq_employee_id.CURRVAL);
COMMIT;
END;
/
3.4 12c+ IDENTITY列 #
sql
-- Oracle 12c引入IDENTITY列
-- 方式1:GENERATED ALWAYS
CREATE TABLE employees (
employee_id NUMBER GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
first_name VARCHAR2(50),
last_name VARCHAR2(50)
);
-- 方式2:GENERATED BY DEFAULT
CREATE TABLE employees (
employee_id NUMBER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
first_name VARCHAR2(50),
last_name VARCHAR2(50)
);
-- 方式3:GENERATED BY DEFAULT ON NULL
CREATE TABLE employees (
employee_id NUMBER GENERATED BY DEFAULT ON NULL AS IDENTITY PRIMARY KEY,
first_name VARCHAR2(50),
last_name VARCHAR2(50)
);
-- IDENTITY列选项
CREATE TABLE employees (
employee_id NUMBER GENERATED BY DEFAULT ON NULL AS IDENTITY
(START WITH 1000 INCREMENT BY 1 CACHE 100) PRIMARY KEY,
first_name VARCHAR2(50),
last_name VARCHAR2(50)
);
-- 查看IDENTITY列信息
SELECT * FROM USER_TAB_IDENTITY_COLS WHERE TABLE_NAME = 'EMPLOYEES';
四、管理序列 #
4.1 修改序列 #
sql
-- 修改序列
ALTER SEQUENCE seq_employee_id
INCREMENT BY 1
MAXVALUE 999999999
NOCYCLE
CACHE 20;
-- 注意:不能修改START WITH值
-- 如果需要重新开始,需要删除重建
-- 重置序列(删除重建)
DROP SEQUENCE seq_employee_id;
CREATE SEQUENCE seq_employee_id
START WITH 1
INCREMENT BY 1;
-- 重置序列(通过调整增量)
-- 假设当前值为100,想重置为1
ALTER SEQUENCE seq_employee_id INCREMENT BY -99;
SELECT seq_employee_id.NEXTVAL FROM DUAL; -- 返回1
ALTER SEQUENCE seq_employee_id INCREMENT BY 1;
4.2 删除序列 #
sql
-- 删除序列
DROP SEQUENCE seq_employee_id;
-- 检查序列是否存在
SELECT SEQUENCE_NAME FROM USER_SEQUENCES WHERE SEQUENCE_NAME = 'SEQ_EMPLOYEE_ID';
4.3 查看序列信息 #
sql
-- 查看序列信息
SELECT
SEQUENCE_NAME,
MIN_VALUE,
MAX_VALUE,
INCREMENT_BY,
CYCLE_FLAG,
CACHE_SIZE,
LAST_NUMBER
FROM USER_SEQUENCES;
-- 查看特定序列
SELECT * FROM USER_SEQUENCES WHERE SEQUENCE_NAME = 'SEQ_EMPLOYEE_ID';
-- 查看所有序列
SELECT SEQUENCE_NAME, LAST_NUMBER FROM USER_SEQUENCES;
五、同义词概述 #
5.1 什么是同义词 #
同义词(Synonym)是数据库对象的别名,可以为表、视图、序列、存储过程等对象创建同义词,简化对象访问。
text
同义词作用
├── 简化对象访问
│ └── 缩短对象名称
├── 隐藏对象位置
│ └── 屏蔽模式名
├── 提供透明性
│ └── 对象重命名不影响应用
└── 跨模式访问
└── 简化权限管理
5.2 同义词类型 #
text
同义词类型
├── 私有同义词
│ └── 只对创建者可见
└── 公共同义词
└── 对所有用户可见
六、创建同义词 #
6.1 创建私有同义词 #
sql
-- 创建私有同义词
CREATE SYNONYM emp FOR hr.employees;
-- 使用同义词
SELECT * FROM emp;
-- 为视图创建同义词
CREATE SYNONYM emp_view FOR hr.v_employee_details;
-- 为序列创建同义词
CREATE SYNONYM emp_seq FOR hr.seq_employee_id;
-- 为存储过程创建同义词
CREATE SYNONYM get_salary FOR hr.get_employee_salary;
6.2 创建公共同义词 #
sql
-- 创建公共同义词
CREATE PUBLIC SYNONYM employees FOR hr.employees;
-- 所有用户都可以访问
SELECT * FROM employees;
-- 创建公共序列同义词
CREATE PUBLIC SYNONYM seq_emp FOR hr.seq_employee_id;
-- 使用公共序列同义词
SELECT seq_emp.NEXTVAL FROM DUAL;
6.3 同义词权限 #
sql
-- 创建私有同义词权限
GRANT CREATE SYNONYM TO user_name;
-- 创建公共同义词权限
GRANT CREATE PUBLIC SYNONYM TO user_name;
-- 删除公共同义词权限
GRANT DROP PUBLIC SYNONYM TO user_name;
-- 使用同义词还需要基础对象的访问权限
GRANT SELECT ON hr.employees TO user_name;
七、管理同义词 #
7.1 删除同义词 #
sql
-- 删除私有同义词
DROP SYNONYM emp;
-- 删除公共同义词
DROP PUBLIC SYNONYM employees;
-- 删除不存在的同义词(避免错误)
DROP SYNONYM IF EXISTS emp;
7.2 查看同义词信息 #
sql
-- 查看私有同义词
SELECT
SYNONYM_NAME,
TABLE_OWNER,
TABLE_NAME
FROM USER_SYNONYMS;
-- 查看所有可访问的同义词
SELECT
OWNER,
SYNONYM_NAME,
TABLE_OWNER,
TABLE_NAME
FROM ALL_SYNONYMS;
-- 查看公共同义词
SELECT
SYNONYM_NAME,
TABLE_OWNER,
TABLE_NAME
FROM DBA_SYNONYMS
WHERE OWNER = 'PUBLIC';
-- 查看特定同义词
SELECT * FROM USER_SYNONYMS WHERE SYNONYM_NAME = 'EMP';
7.3 同义词依赖 #
sql
-- 查看同义词依赖的对象
SELECT
NAME,
TYPE,
REFERENCED_NAME,
REFERENCED_TYPE
FROM USER_DEPENDENCIES
WHERE NAME = 'EMP' AND TYPE = 'SYNONYM';
-- 查看依赖同义词的对象
SELECT
NAME,
TYPE
FROM USER_DEPENDENCIES
WHERE REFERENCED_NAME = 'EMP' AND REFERENCED_TYPE = 'SYNONYM';
八、同义词应用场景 #
8.1 简化对象访问 #
sql
-- 原始访问方式
SELECT * FROM hr.employees;
SELECT * FROM hr.departments;
SELECT * FROM hr.jobs;
-- 创建同义词简化
CREATE SYNONYM emp FOR hr.employees;
CREATE SYNONYM dept FOR hr.departments;
CREATE SYNONYM jobs FOR hr.jobs;
-- 使用同义词
SELECT * FROM emp;
SELECT * FROM dept;
SELECT * FROM jobs;
8.2 跨模式访问 #
sql
-- 场景:应用用户需要访问HR模式下的表
-- 方式1:直接授权
GRANT SELECT ON hr.employees TO app_user;
-- 应用用户需要使用 hr.employees
-- 方式2:使用公共同义词
CREATE PUBLIC SYNONYM employees FOR hr.employees;
GRANT SELECT ON hr.employees TO PUBLIC;
-- 应用用户可以直接使用 employees
8.3 数据库迁移 #
sql
-- 场景:表从一个模式迁移到另一个模式
-- 原始状态
-- 应用使用 hr.employees
-- 迁移后
-- 表移动到 hr_new 模式
-- 方式1:修改所有应用代码(不推荐)
-- 方式2:使用同义词(推荐)
-- 删除旧同义词
DROP PUBLIC SYNONYM employees;
-- 创建新同义词
CREATE PUBLIC SYNONYM employees FOR hr_new.employees;
-- 应用无需修改
8.4 开发测试环境 #
sql
-- 场景:开发和测试环境使用不同的表
-- 开发环境
CREATE SYNONYM orders FOR dev.orders;
-- 测试环境
CREATE SYNONYM orders FOR test.orders;
-- 生产环境
CREATE SYNONYM orders FOR prod.orders;
-- 应用代码统一使用 orders
九、序列与同义词最佳实践 #
9.1 序列最佳实践 #
sql
-- 1. 为序列命名
-- 推荐:seq_表名 或 seq_用途
CREATE SEQUENCE seq_employee_id;
CREATE SEQUENCE seq_order_no;
-- 2. 合理设置缓存
-- 高并发场景使用缓存
CREATE SEQUENCE seq_high_concurrency
CACHE 1000;
-- 需要连续序列号时不使用缓存
CREATE SEQUENCE seq_invoice_no
NOCACHE;
-- 3. 主键使用IDENTITY列(12c+)
CREATE TABLE employees (
employee_id NUMBER GENERATED BY DEFAULT ON NULL AS IDENTITY PRIMARY KEY,
first_name VARCHAR2(50)
);
-- 4. 监控序列使用
SELECT
SEQUENCE_NAME,
LAST_NUMBER,
CACHE_SIZE
FROM USER_SEQUENCES;
9.2 同义词最佳实践 #
sql
-- 1. 命名规范
-- 同义词名应简洁明了
CREATE SYNONYM emp FOR hr.employees; -- 好
CREATE SYNONYM e FOR hr.employees; -- 不推荐
-- 2. 公共同义词谨慎使用
-- 避免名称冲突
-- 避免过度授权
-- 3. 文档化同义词
-- 记录同义词与实际对象的映射关系
COMMENT ON SYNONYM emp IS 'HR模式员工表同义词';
-- 4. 定期审查同义词
-- 检查无效同义词
SELECT
SYNONYM_NAME,
TABLE_OWNER,
TABLE_NAME
FROM USER_SYNONYMS s
WHERE NOT EXISTS (
SELECT 1 FROM ALL_TABLES t
WHERE t.OWNER = s.TABLE_OWNER
AND t.TABLE_NAME = s.TABLE_NAME
);
十、常见问题 #
10.1 序列问题 #
sql
-- 问题1:序列跳号
-- 原因:CACHE导致,回滚,实例崩溃
-- 解决:接受跳号或使用NOCACHE
-- 问题2:序列耗尽
-- 原因:达到MAXVALUE
-- 解决:扩大MAXVALUE或使用CYCLE
ALTER SEQUENCE seq_employee_id MAXVALUE 999999999999;
-- 问题3:重置序列
-- 解决:调整增量或删除重建
ALTER SEQUENCE seq_employee_id INCREMENT BY -99;
SELECT seq_employee_id.NEXTVAL FROM DUAL;
ALTER SEQUENCE seq_employee_id INCREMENT BY 1;
10.2 同义词问题 #
sql
-- 问题1:同义词无效
-- 原因:基础对象被删除或重命名
-- 解决:重建同义词
DROP SYNONYM emp;
CREATE SYNONYM emp FOR hr.employees;
-- 问题2:同义词权限不足
-- 原因:缺少基础对象的访问权限
-- 解决:授予基础对象权限
GRANT SELECT ON hr.employees TO user_name;
-- 问题3:公共同义词名称冲突
-- 原因:多个模式有同名对象
-- 解决:使用私有同义词或重命名
十一、总结 #
序列与同义词要点:
| 对象 | 用途 | 关键命令 |
|---|---|---|
| 序列 | 生成唯一数字 | CREATE/ALTER/DROP SEQUENCE |
| 私有同义词 | 私有别名 | CREATE/DROP SYNONYM |
| 公共同义词 | 公共别名 | CREATE/DROP PUBLIC SYNONYM |
序列使用要点:
- 使用NEXTVAL获取下一个值
- 使用CURRVAL获取当前值
- 12c+推荐使用IDENTITY列
- 合理设置缓存提高性能
同义词使用要点:
- 简化对象访问
- 隐藏对象位置
- 支持数据库迁移
- 注意权限管理
下一步,让我们学习数据插入!
最后更新:2026-03-27