Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1nQEpk-00019Q-F1 for pgsql-sql@arkaria.postgresql.org; Fri, 04 Mar 2022 20:47:29 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.92) (envelope-from ) id 1nQEpj-0002cf-BS for pgsql-sql@arkaria.postgresql.org; Fri, 04 Mar 2022 20:47:27 +0000 Received: from makus.postgresql.org ([2001:4800:3e1:1::229]) by malur.postgresql.org with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1nQEpi-0002bd-V2 for pgsql-sql@lists.postgresql.org; Fri, 04 Mar 2022 20:47:27 +0000 Received: from forward501p.mail.yandex.net ([2a02:6b8:0:1472:2741:0:8b7:120]) by makus.postgresql.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1nQEpe-0001b7-WA for pgsql-sql@lists.postgresql.org; Fri, 04 Mar 2022 20:47:25 +0000 Received: from vla1-395bc165982e.qloud-c.yandex.net (vla1-395bc165982e.qloud-c.yandex.net [IPv6:2a02:6b8:c0d:179c:0:640:395b:c165]) by forward501p.mail.yandex.net (Yandex) with ESMTP id A6ED262123CA; Fri, 4 Mar 2022 23:47:13 +0300 (MSK) Received: from vla5-047c0c0d12a6.qloud-c.yandex.net (vla5-047c0c0d12a6.qloud-c.yandex.net [2a02:6b8:c18:3484:0:640:47c:c0d]) by vla1-395bc165982e.qloud-c.yandex.net (mxback/Yandex) with ESMTP id vg0JGem3kA-lDfait2f; Fri, 04 Mar 2022 23:47:13 +0300 X-Yandex-Fwd: 2 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=yandex.ru; s=mail; t=1646426833; bh=ME8BD7giYKUS7/lPFz5E8ywu6FPcMNNUsVUfaZ2drEw=; h=In-Reply-To:From:Cc:Date:References:To:Subject:Message-ID; b=FnVFi2uRkUnf9+rkfkBMVPtRBhE3ATlNRmLgCjignuI19075cpj0R9nZ+Z91e2xIu y9KSC48AgHGbSUqZs3I3L+IWX41ZhyWuxzfy1OZkupStAwcweDJNkOuisi9OS9GJJB T61bvuWeYg00EViXQmJ6ZsMdVSe6JHgRI0TKGSi0= Authentication-Results: vla1-395bc165982e.qloud-c.yandex.net; dkim=pass header.i=@yandex.ru Received: by vla5-047c0c0d12a6.qloud-c.yandex.net (smtp/Yandex) with ESMTPSA id dFOCGTR4V3-lCJK3De1; Fri, 04 Mar 2022 23:47:12 +0300 (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (Client certificate not present) Subject: Re: unique index with several columns To: Tom Lane Cc: "Voillequin, Jean-Marc" , "David G. Johnston" , "pgsql-sql@lists.postgresql.org" References: <6699c0e9-e358-1fc2-7ce4-7a24d4bc419e@yandex.ru> <3966274.1646418725@sss.pgh.pa.us> From: Alexey M Boltenkov Message-ID: <8b4b7a41-5181-60db-2bd9-a6fabcd6226f@yandex.ru> Date: Fri, 4 Mar 2022 23:47:12 +0300 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101 Firefox/52.0 Thunderbird/52.9.1 MIME-Version: 1.0 In-Reply-To: <3966274.1646418725@sss.pgh.pa.us> Content-Type: text/plain; charset=utf-8; format=flowed Content-Transfer-Encoding: 8bit Content-Language: en-US List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk On 03/04/22 21:32, Tom Lane wrote: > Alexey M Boltenkov writes: >> You need the new v15 feature: >> NULLS [NOT] DISTINCT > That won't replicate the behavior shown by the OP though. > In particular, not the weird inconsistency for all-null rows. > > regards, tom lane > But why? # create table t(c1 char, c2 char); CREATE TABLE # create unique index idx on t(c1,c2) nulls not distinct where c1 is not null or c2 is not null; CREATE INDEX # insert into t(c1,c2) values (null,null); INSERT 0 1 # insert into t(c1,c2) values (null,null); INSERT 0 1 # insert into t(c1,c2) values ('a',null); INSERT 0 1 # insert into t(c1,c2) values ('a',null); ERROR:  23505: duplicate key value violates unique constraint "idx" DETAIL:  Key (c1, c2)=(a, null) already exists. SCHEMA NAME:  public TABLE NAME:  t CONSTRAINT NAME:  idx LOCATION:  _bt_check_unique, nbtinsert.c:664 # \d+ t                                                Table "public.t"  Column │     Type     │ Collation │ Nullable │ Default │ Storage │ Compression │ Stats target │ Description ════════╪══════════════╪═══════════╪══════════╪═════════╪══════════╪═════════════╪══════════════╪═════════════  c1     │ character(1) │           │          │         │ extended │             │              │  c2     │ character(1) │           │          │         │ extended │             │              │ Indexes:     "idx" UNIQUE, btree (c1, c2) NULLS NOT DISTINCT WHERE c1 IS NOT NULL OR c2 IS NOT NULL Access method: heap # table t;  c1 │ c2 ════╪════  ¤  │ ¤  ¤  │ ¤  a  │ ¤ (3 rows)