1. 概述
1.1 约束定义
约束(Constraint)是Oracle数据库中用于确保数据完整性的规则,通过限制列中可存储的值或多列间的关系,保证数据符合业务规则。Oracle 19c支持多种约束类型,且在兼容性和性能上对约束机制进行了优化。
1.2 约束作用
- 保证数据准确性(如主键唯一标识记录)
- 维护数据一致性(如外键关联父表数据)
- 减少应用层数据校验逻辑,降低冗余开发
2. 约束类型及语法
2.1 主键约束(PRIMARY KEY)
定义
唯一标识表中的每条记录,要求列值非空且唯一,一个表只能有一个主键。
语法示例-- 建表时创建(列级)
CREATE TABLE employees ( emp_id NUMBER(10) CONSTRAINT emp_pk PRIMARY KEY, emp_name VARCHAR2(50) NOT NULL );
-- 建表时创建(表级,支持复合主键)
CREATE TABLE employee_roles ( emp_id NUMBER(10), role_id NUMBER(10), CONSTRAINT emp_role_pk PRIMARY KEY (emp_id, role_id) );
-- 建表后添加
ALTER TABLE departments ADD CONSTRAINT dept_pk PRIMARY KEY (dept_id);
2.2 外键约束(FOREIGN KEY)
定义
用于维护两个表之间的关联关系,外键列的值必须匹配父表主键列的值或为NULL。
语法示例-- 基础外键(引用父表主键)
CREATE TABLE employees ( emp_id NUMBER(10) PRIMARY KEY, dept_id NUMBER(10), CONSTRAINT emp_dept_fk FOREIGN KEY (dept_id) REFERENCES departments(dept_id) );
-- 带级联操作的外键(Oracle 19c支持)
CREATE TABLE orders ( order_id NUMBER(10) PRIMARY KEY, cust_id NUMBER(10), CONSTRAINT ord_cust_fk FOREIGN KEY (cust_id) REFERENCES customers(cust_id)
ON DELETE CASCADE -- 父表记录删除时,子表关联记录同步删除
ON UPDATE SET NULL -- 父表主键更新时,子表外键设为NULL );
2.3 唯一约束(UNIQUE)
定义
确保列或列组合的值唯一,但允许NULL值(多个NULL不视为重复)。
语法示例-- 单列唯一
CREATE TABLE users ( user_id NUMBER(10) PRIMARY KEY, email VARCHAR2(100) CONSTRAINT uk_email UNIQUE );
-- 多列唯一(组合值唯一)
CREATE TABLE products ( prod_id NUMBER(10) PRIMARY KEY, prod_code VARCHAR2(20), version NUMBER(3), CONSTRAINT uk_prod_version UNIQUE (prod_code, version) );
2.4 检查约束(CHECK)
定义
限制列值必须满足指定条件,Oracle 19c支持更复杂的条件表达式(如子查询除外)。
语法示例-- 基础检查(数值范围)
CREATE TABLE employees ( emp_id NUMBER(10) PRIMARY KEY, salary NUMBER(10,2) CONSTRAINT chk_salary CHECK (salary > 0), hire_date DATE CONSTRAINT chk_hire_date CHECK (hire_date <= SYSDATE) );
-- 字符串匹配检查
CREATE TABLE customers ( cust_id NUMBER(10) PRIMARY KEY, gender CHAR(1) CONSTRAINT chk_gender CHECK (gender IN ('M', 'F', 'U')) );
-- 多列关联检查(表级约束)
CREATE TABLE orders ( order_id NUMBER(10) PRIMARY KEY, order_date DATE, ship_date DATE, CONSTRAINT chk_dates CHECK (ship_date >= order_date) );
2.5 非空约束(NOT NULL)
定义
强制列不能包含NULL值,是唯一只能定义在列级的约束。
CREATE TABLE employees (
emp_id NUMBER(10) PRIMARY KEY,
emp_name VARCHAR2(50) CONSTRAINT nn_emp_name NOT NULL,
phone VARCHAR2(20) -- 允许NULL
);
-- 建表后添加非空约束(需确保列无NULL值)
ALTER TABLE employees MODIFY (email VARCHAR2(100) CONSTRAINT nn_emp_email NOT NULL);
3. 约束管理与维护
3.1 查看约束信息-- 查询表的所有约束
SELECT constraint_name, constraint_type, search_condition, status FROM user_constraints WHERE table_name = 'EMPLOYEES';
-- 查询约束对应的列
SELECT constraint_name, column_name, position FROM user_cons_columns WHERE table_name = 'EMPLOYEES';
3.2 启用/禁用约束-- 禁用约束(保留定义,暂时不生效)
ALTER TABLE employees DISABLE CONSTRAINT emp_dept_fk;
-- 启用约束(重新生效,自动校验现有数据)
ALTER TABLE employees enable CONSTRAINT emp_dept_fk;
-- 启用约束时跳过数据校验(适用于大量历史数据,Oracle 19c高效支持)
ALTER TABLE employees enable NOVALIDATE CONSTRAINT emp_dept_fk;
3.3 删除约束ALTER TABLE employees
DROP CONSTRAINT uk_email;-- 删除主键约束(若有外键引用,需先删除外键或级联删除)
ALTER TABLE departments DROP PRIMARY KEY CASCADE; -- 级联删除引用该主键的外键
3.4 修改约束(重命名)ALTER TABLE employees
RENAME CONSTRAINT chk_salary TO chk_emp_salary;
4. Oracle 19c约束增强特性
4.1 非空约束增强
支持在ALTER TABLE MODIFY时更灵活地修改非空约束,无需重建表:
-- 从非空改为可空
ALTER TABLE employees MODIFY (phone NULL);
-- 从可空改为非空(需确保列无NULL值)
ALTER TABLE employees MODIFY (phone CONSTRAINT nn_emp_phone NOT NULL);
4.2 检查约束性能优化
Oracle 19c对检查约束的解析和执行进行了优化,尤其是包含函数的复杂条件(如CHECK (LENGTH(emp_name) > 2)),执行效率较12c提升约30%。
4.3 延迟约束验证
支持事务提交时再验证约束(默认即时验证),适合批量插入/更新场景:-- 创建延迟约束
-- 事务中暂时允许违反约束,提交时验证
CREATE TABLE transactions ( trans_id NUMBER(10) PRIMARY KEY, amount NUMBER(10,2), CONSTRAINT chk_amount CHECK (amount > 0) DEFERRABLE INITIALLY DEFERRED );
INSERT INTO transactions VALUES (1, -100); -- 不报错 COMMIT; -- 提交时校验,报错并回滚
5. 最佳实践
5.1 命名规范
- 主键:
PK_<表名>(如PK_EMPLOYEES) - 外键:
FK_<子表名>_<父表名>(如FK_EMP_DEPT) - 唯一约束:
UK_<表名>_<列名>(如UK_USERS_EMAIL) - 检查约束:
CHK_<表名>_<列名>(如CHK_EMP_SALARY) - 非空约束:
NN_<表名>_<列名>(如NN_EMP_NAME)
5.2 性能考虑
- 避免在频繁更新的列上创建过多约束(尤其是检查约束)
- 复合主键的列顺序应基于查询频率(高频过滤列在前)
- 外键关联的列建议建立索引(避免父表删除/更新时全表扫描):
CREATE INDEX idx_emp_dept ON employees(dept_id); -- 外键列索引
5.3 业务适配
- 历史数据迁移时,可先禁用约束,迁移完成后启用
NOVALIDATE(跳过历史数据校验) - 复杂业务规则优先用检查约束(数据库层保障),而非仅依赖应用程序
- 外键的级联操作需谨慎使用(
ON DELETE CASCADE可能导致批量数据删除)
6. 常见问题及解决
6.1 约束冲突报错
- 错误:
ORA-00001: 违反唯一约束条件 - 解决:检查插入/更新的值是否重复,或使用
MERGE语句避免重复插入
6.2 外键引用失败
- 错误:
ORA-02291: 完整性约束条件 violated - 未找到父项关键字 - 解决:确保子表外键值在父表中存在,或允许外键为NULL
6.3 启用约束失败
- 错误:
ORA-02293: 无法验证约束 - 找到违反约束的数据 - 解决:清理不符合约束的脏数据,或使用
ENABLE NOVALIDATE跳过验证
628

被折叠的 条评论
为什么被折叠?



