You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django迁移PostgreSQL数据库时触发UniqueViolation错误:cpf_funcionario字段存在重复空值

解决Django迁移时PostgreSQL唯一索引创建失败的问题

问题根源

你遇到的django.db.utils.IntegrityError本质是PostgreSQL的唯一约束规则导致的:当你给Funcionario模型的cpf_funcionario字段添加unique=True后,Django会尝试在数据库创建唯一索引,但你的models_funcionario表中已经存在多条cpf_funcionario为空值的记录。在PostgreSQL中,空值会被视为相等的,所以这些重复的空值违反了唯一约束,导致索引创建失败。

解决方案步骤

1. 确认数据库中的重复数据

首先连接到你的PostgreSQL数据库,执行以下SQL查询,验证空值记录的数量:

SELECT cpf_funcionario, COUNT(*) 
FROM models_funcionario 
GROUP BY cpf_funcionario 
HAVING COUNT(*) > 1;

你会看到cpf_funcionario为空的记录条数大于1,这就是问题的核心。

2. 处理重复的空值数据

根据你的业务需求,选择以下两种方案之一:

方案A:给空值记录填充唯一的CPF值

如果业务要求每个员工必须有唯一的CPF,你需要手动给这些空值记录补充合法且唯一的CPF:

-- 示例:给指定ID的空值记录设置CPF
UPDATE models_funcionario 
SET cpf_funcionario = '123.456.789-00' 
WHERE cpf_funcionario IS NULL AND id = 1;

-- 重复此操作,给所有空值记录分配唯一的CPF

完成数据修复后,重新执行迁移命令:

(env)$ python manage.py migrate
方案B:允许CPF为空但仅非空值唯一(业务允许的情况)

如果业务允许员工暂时没有CPF,但要求非空的CPF必须唯一,你需要修改模型的字段定义,使用部分唯一索引来绕过空值的冲突:

首先修改Funcionario模型:

from django.db.models import Q, Index

class Funcionario(AbstractUser):
    rg_funcionario = models.CharField(max_length=200)
    # 保留null=True和blank=True,移除原有的unique=True
    cpf_funcionario = models.CharField(max_length=200, null=True, blank=True)
    id_funcao_funcionario = models.ForeignKey(FuncaoFuncionario, on_delete=models.SET_NULL, null=True)
    # ... 其他字段保持不变

    class Meta:
        # 添加部分唯一索引:仅当cpf_funcionario非空时强制唯一
        indexes = [
            Index(fields=['cpf_funcionario'], condition=Q(cpf_funcionario__isnull=False), name='unique_cpf_not_null')
        ]

然后重新生成迁移文件并执行:

(env)$ python manage.py makemigrations
(env)$ python manage.py migrate

3. 回滚错误的迁移(可选)

如果你已经生成了导致问题的0018_auto_20210809_1124迁移文件,可以先回滚到上一个成功的迁移状态,再处理数据或修改模型:

(env)$ python manage.py migrate models 0017_alter_horarioservico_unidade

额外提示

  • 后续添加唯一约束前,一定要先检查现有数据是否符合约束要求,避免类似问题。
  • PostgreSQL对空值在唯一约束中的处理逻辑和MySQL不同,这点需要特别注意哦。

内容的提问来源于stack exchange,提问作者LucasBorges-Santos

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.30 02:57:30