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

puc*_*hal 6 postgresql

我对多列可能包含 NULL 值的 Postgres 唯一约束有问题。

让我们假设这种情况:

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;
Run Code Online (Sandbox Code Playgroud)

Insert 将插入 ('foo', 'bar') 一次和 ('foo', NULL) 两次(即使直觉说它应该插入一次)。

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

CREATE UNIQUE INDEX indx ON test (foo) WHERE bar IS NULL;
Run Code Online (Sandbox Code Playgroud)

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

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

Lau*_*lbe 7

禁止 NULL 的良好解决方案的替代方法是创建唯一索引。

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

CREATE UNIQUE INDEX ON test (
   coalesce(foo, '@@'),
   coalesce(bar, '@@')
);
Run Code Online (Sandbox Code Playgroud)

  • @puchal,请注意 PG 15 的新功能 — F292 «独特的空处理»。 (2认同)

Nae*_*dov 5

顺便说一句,从版本 15 开始,Postgress 支持 SQL 规范 F292 \xc2\xabUnique nulltreatment\xc2\xbb 的可选功能。它允许在唯一约束中控制行为 NULL 值

\n
create table ... (\n  ..........,\n  UNIQUE NULLS [NOT] DISTINCT (...)\n);\n
Run Code Online (Sandbox Code Playgroud)\n