【问题标题】:How to enforce uniqueness with NULL values in PostgreSQL如何在 PostgreSQL 中使用 NULL 值强制唯一性
【发布时间】:2023-03-28 18:54:01
【问题描述】:

我有一个具有不可为空 CharField 和 2 x 可空 CharField 的模型:

class MyModel(models.Model):
    name = models.CharField('Name', max_length=255, null=False)
    title = models.CharField('Title', max_length=255, blank=True)
    position = models.CharField('Position', max_length=255, blank=True)

我想确保 nametitleposition 一起是唯一的,所以使用 UniqueConstraint

def Meta:
    constraints = [
            models.UniqueConstraint(
                fields=['name', 'title', 'position'],
                name="unique_name_title_position"
            ),
        ]

但是,如果 titleNone,则此约束失败。

寻找原因,这是因为您可以将 NULL 值插入具有 UNIQUE 约束的列中,因为 NULL 是缺少值,因此它永远不会等于其他 NULL 值并且不考虑重复值。这意味着如果其中一个值为NULL,则可以插入看似重复的行。

在 Django 中严格执行这种唯一性的正确方法是什么?

【问题讨论】:

  • 使可为空的列也不能为空?你想用这个解决什么问题?
  • 你用的是什么数据库
  • @iklinac PostgreSQL 12
  • @yedpodtrzitko 这不符合我的用例。例如。如果titleposition 为NULL,我只想要一个name。如果只有position 为NULL,我想要一个nametitle

标签: django postgresql django-models


【解决方案1】:

您可以为titleposition 选择从未出现过的值并使用如下索引:

CREATE UNIQUE INDEX ON mytable (
   name,
   coalesce(title, '#impossible#'),
   coalesce(position, '#impossible#'),
);

这会将 NULL 值替换为其他值,从而防止重复。

【讨论】:

    【解决方案2】:

    UniqueConstraint 不是在 Django 级别上强制执行,而是直接在数据库上执行。

    例如,PostgreSQL 允许多个 Null 记录唯一,而 MSSQL 则不允许

    您可以使用CheckConstraint 检查每个列子集是否具有CheckConstraint,但您会发现这很乏味,因为它要求每个组合都是唯一的indexed


    为了避免整个混乱,您可以按照CharField 的 Django 指南进行操作 如documented

    避免在基于字符串的字段(例如 CharField 和 文本域。如果基于字符串的字段具有 null=True,则意味着它具有 “无数据”的两个可能值:NULL 和空字符串。多数情况 在这种情况下,“无数据”有两个可能的值是多余的;这 Django 约定是使用空字符串,而不是 NULL。一个例外 当 CharField 同时设置了 unique=True 和 blank=True 时。在这个 在这种情况下,需要 null=True 以避免违反唯一约束 保存具有空白值的多个对象时。

    检查空字符串的唯一性

    【讨论】:

      猜你喜欢
      • 2011-03-18
      • 2023-02-04
      • 2011-02-18
      • 2021-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-12-22
      相关资源
      最近更新 更多