五类约束
- NOT NULL:最基础,列级约束,不能命名为表级约束
- PRIMARY KEY:唯一 + 非空,自动创建唯一索引,一张表只能有一个
- UNIQUE:允许 NULL(且多个 NULL 互不冲突),也自动建唯一索引
- FOREIGN KEY:引用父表主键或唯一键,保证引用完整性
- CHECK:布尔表达式,NULL 会使检查通过(这一点常被忽略)
CREATE TABLE project (
project_id NUMBER(6),
project_name VARCHAR2(50),
dept_id NUMBER(4),
status VARCHAR2(10),
budget NUMBER(12,2),
start_date DATE,
CONSTRAINT pk_project PRIMARY KEY (project_id),
CONSTRAINT uk_project_name UNIQUE (project_name),
CONSTRAINT ck_project_status CHECK (status IN ('PLAN', 'ACTIVE', 'DONE')),
CONSTRAINT ck_project_budget CHECK (budget >= 0),
CONSTRAINT fk_project_dept FOREIGN KEY (dept_id)
REFERENCES departments (department_id)
ON DELETE SET NULL
);只作示例阅读:5 行写入限制下只开放单独创建普通空表;CTAS、删表、清空表、改结构、触发器和存储程序不允许执行。请在独立学习数据库中练习。
外键的级联行为
-- 建表时 project.dept_id 上已经有一个外键 fk_project_dept。
-- 同一个列不能同时挂两个指向同一父表的外键(会报 ORA-02275),
-- 所以先把它删掉,再演示不同的删除策略。
ALTER TABLE project DROP CONSTRAINT fk_project_dept;
-- 1) 默认:父表有子记录时禁止删除
ALTER TABLE project ADD CONSTRAINT fk_dept
FOREIGN KEY (dept_id) REFERENCES departments (department_id);
-- 下面两种是替代方案。同名约束不能重复添加,
-- 想换成哪种就先删掉上面的约束再重建:
--
-- 2) 级联删除:删父表同时删掉子表记录
-- ALTER TABLE project DROP CONSTRAINT fk_dept;
-- ALTER TABLE project ADD CONSTRAINT fk_dept
-- FOREIGN KEY (dept_id) REFERENCES departments (department_id)
-- ON DELETE CASCADE;
--
-- 3) 置空:删父表把子表外键列设为 NULL
-- ALTER TABLE project DROP CONSTRAINT fk_dept;
-- ALTER TABLE project ADD CONSTRAINT fk_dept
-- FOREIGN KEY (dept_id) REFERENCES departments (department_id)
-- ON DELETE SET NULL;只作示例阅读:5 行写入限制下只开放单独创建普通空表;CTAS、删表、清空表、改结构、触发器和存储程序不允许执行。请在独立学习数据库中练习。
启用、禁用与延迟校验
- 约束类型代码:P 主键、U 唯一、R 外键、C 检查、V 带 WITH CHECK OPTION 的视图、O 只读视图(19c 起另有 H、F、S)。注意:没有 N 这个类型,NOT NULL 是以 C(检查约束)形式存储的
- 禁用主键约束会连带影响引用它的外键
- 给大表加约束时,先清理脏数据,再用 NOVALIDATE 快速启用,最后单独 VALIDATE
-- 禁用/启用(ENABLE NOVALIDATE 只对新增数据生效,不校验存量)
ALTER TABLE project DISABLE CONSTRAINT ck_project_status;
ALTER TABLE project ENABLE CONSTRAINT ck_project_status;
-- 启用但不校验历史数据(不锁表,快速上线)
ALTER TABLE project ENABLE NOVALIDATE CONSTRAINT ck_project_status;
-- 延迟约束:事务提交时才检查,便于中间状态违反约束
-- 同名约束已存在,先删再建
ALTER TABLE project DROP CONSTRAINT fk_dept;
ALTER TABLE project ADD CONSTRAINT fk_dept
FOREIGN KEY (dept_id) REFERENCES departments (department_id)
DEFERRABLE INITIALLY DEFERRED;只作示例阅读:5 行写入限制下只开放单独创建普通空表;CTAS、删表、清空表、改结构、触发器和存储程序不允许执行。请在独立学习数据库中练习。
SELECT c.constraint_name,
c.constraint_type, -- P/U/R/C
c.status,
c.validated,
cc.column_name,
c.r_constraint_name -- 外键指向的父约束
FROM user_constraints c
LEFT JOIN user_cons_columns cc
ON cc.constraint_name = c.constraint_name
WHERE c.table_name = 'PROJECT'
ORDER BY c.constraint_type, c.constraint_name;在你的专用沙箱里执行打开演练场