You need to enable JavaScript to run this app. SQL与Oracle数据库表约束:禁止重复插入同名称且薪资为空的记录
优惠活动
大模型
产品
解决方案
定价
更多

SQL与Oracle数据库表约束:禁止重复插入同名称且薪资为空的记录

核心管控规则说明
  • 约束生效边界:当表中已存在某Name字段值、且对应salary为NULL的记录时,禁止再插入相同Name值、salary为NULL的重复行
  • 约束豁免范围:同Name值下,salary为非NULL值的记录,无论插入多少条都不受规则限制,可正常写入
  • 典型场景验证:表中已存在Id=1、Name=A、age=30、salary=NULL的记录时,插入Id=3、Name=A、salary=NULL的重复行必须被拦截
数据库层实现方案

通用SQL实现(PostgreSQL、SQL Server、MySQL 8.0+)

对于原生支持部分过滤索引的数据库,不需要复杂逻辑,直接创建带范围限定的唯一索引即可实现规则,性能最优。

首先创建示例业务表:

CREATE TABLE employee (
  Id INT PRIMARY KEY,
  Name VARCHAR(50) NOT NULL,
  age INT,
  salary DECIMAL(10,2)
);

然后创建带过滤条件的唯一约束,仅对salary为NULL的行做Name值的唯一性校验:

CREATE UNIQUE INDEX uk_employee_name_null_salary
ON employee (Name)
WHERE salary IS NULL;

*效果说明:

  • 插入Name=A、salary=NULL的第一条记录时,可正常写入
  • 再次插入同Name、同salary为NULL的重复行时,触发唯一索引冲突,直接被拦截
  • 所有salary为非NULL的记录,均不在索引校验范围内,不会被规则误拦截*

Oracle 实现方案

Oracle 不支持普通唯一索引附带WHERE过滤条件,因此利用Oracle唯一索引的原生特性实现完全相同的管控效果:

Oracle 唯一索引不会对「索引键值为全NULL」的行做唯一性校验,多个NULL键值可同时存在于索引中,不会触发冲突。

基于该特性,通过CASE表达式生成索引键值,将需要约束的行映射为可校验的非空键值,不需要约束的行映射为NULL键值:

CREATE UNIQUE INDEX uk_employee_name_null_salary
ON employee (
  CASE
    WHEN salary IS NULL THEN Name
    ELSE NULL
  END
);

*效果说明:

  1. 当插入salary为NULL、Name=X的记录时,索引键值为Name值X,第一次插入可正常通过校验;后续重复插入同规则的行时,因键值X重复触发唯一冲突,被拦截
  2. 当插入任意salary非NULL的记录时,索引键值为NULL,不会被纳入唯一性校验范围,可自由插入,无规则误伤*
方案优势
  • 均为数据库引擎层面的原生约束,并发写入场景下可保证规则的原子性生效,不存在触发器/应用层校验的并发幻读漏洞
  • 校验逻辑由数据库优化器自动执行,性能远高于行级触发器方案

内容的提问来源于stack exchange,提问作者user1494438

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.23 10:36:04