当前位置: 首页 > 知识库问答 >
问题:

Postgres-具有多列和空值的唯一约束

禄俊逸
2023-03-14

我对Postgres Unique约束有问题,该约束包含多个可能包含空值的列。

让我们假设这种情况:

CREATE TEMP TABLE test (
  foo TEXT,
  bar TEXT,
  UNIQUE (foo, bar)
);

INSERT INTO test
VALUES 
  ('foo', NULL),
  ('foo', NULL),
  ('foo', 'bar'),
  ('foo', 'bar')
ON CONFLICT (foo, bar) DO NOTHING;

Insert将插入('foo',bar')一次和('foo',NULL)两次(尽管直觉告诉它应该插入一次)。

在这种情况下,解决方案非常简单。我可以添加唯一的索引

CREATE UNIQUE INDEX indx ON test (foo) WHERE bar IS NULL;

但是当有更多的列和不同的类型(不仅仅是文本)时,问题就开始了。假设我们有10列,其中9列可以有NULL值。也许我可以用大量的限制来解决它,但这一点都不方便。

有没有更简单的方法来保持这样一行的唯一性?

共有2个答案

廉高邈
2023-03-14

一般来说,您可以考虑列定义,因为两者都被表示为文本,可以让它们不可空,并提供默认值为“(空字符串)”。这样你就可以确定,foo不会被保存两次。此外,空值在实践中也不是很好,因为它只是缺少值的一个标志。

CREATE TEMP TABLE test (
  foo TEXT DEFAULT '' NOT NULL,
  bar TEXT DEFAULT '' NOT NULL,
  UNIQUE (foo, bar)
);
丁和歌
2023-03-14

一个替代禁止NULL的好方法是创建一个唯一的索引。

您所需要的只是一个保证不会出现在数据集中的值(在我的示例中,'@'):

CREATE UNIQUE INDEX ON test (
   coalesce(foo, '@@'),
   coalesce(bar, '@@')
);
 类似资料:
  • 我正在运行Postgres 9.5,并试图基于3个字段创建一个唯一的约束。我遇到的问题是,其中两列可以为NULL,因此这些字段为NULL的行不会违反唯一约束。我的目标是将其作为一个约束,因为我正在尝试更新冲突(UPSERT)。 桌子的结构是这样的 我在这里发现了另一个问题,我可以按照以下方式做一些事情 我不确定在where子句中有两个字段时这是否真的有效,但如何在冲突时调用这个唯一索引呢? 或者我

  • 我想用插页。。请务必更新。。对两列具有唯一约束的表的语法。这可能吗? mytable对col1和col2有单独的唯一约束。 我可以写: 然而,这不起作用: 错误:冲突时,更新是否需要推理规范或约束名称 这也不起作用: 错误:不存在与冲突规范匹配的唯一或排除约束 这种语法似乎是为两列上的单一复合唯一约束而设计的,而不是两个约束。 如果违反了其中一个唯一约束,有没有办法进行条件更新?这个问题是如何在博

  • 当我试图创建第二个表时,我遇到了以下错误,但我不知道为什么。对于表patente,我希望能够将(idfunconario,titulo)作为主键。正如其他主题中所建议的,我已经尝试将唯一约束设置为“唯一(IDFunconario,titulo)”。 消息错误: 错误:没有唯一的约束匹配引用表"public acao"的给定键SQL状态:42830 我在64位的Windows 8.1上使用Postg

  • 问题内容: 我正在将SEAM 2 / Hibernate与PostgreSQL 9数据库一起使用。我有下表 我想添加一个约束,以确保每个新条目都具有active_band_user和active_band_date的唯一组合。 每秒可能有许多次尝试插入,因此我需要尽可能地提高效率,是否可以在实体映射中使用SEAM /hibernate注释? 提前致谢 问题答案: 没有Hibernate注释在插入/

  • 问题内容: 我们有一个遗留数据库架构,该架构具有一些有趣的设计决策。直到最近,我们仅支持Oracle和SQL Server,但是我们试图添加对PostgreSQL的支持,这带来了一个有趣的问题。我已经搜索了Stack Overflow和Internet的其余部分,但我不认为这种特殊情况是重复的。 对于唯一约束中的可为空的列,Oracle和SQL Server的行为相同,这实际上是在执行唯一检查时忽

  • 问题内容: 会根据其位置而不是其值来生成其元素被视为唯一的元素。所以基本上我想避免重复这样的事情: 之后的过滤是不可能的,因为在我的情况下,排列的数量太大。 有人知道合适的算法吗? 非常感谢你! 编辑: 我基本上想要的是以下内容: 这是不可能的,因为sorted创建列表并且itertools.product的输出太大。 抱歉,我应该已经描述了实际问题。 问题答案: 结果: 编辑(这是如何工作的):