检查postgres表中列的唯一性

问题描述

作为较大过程的一部分,我需要确保表中列中的值是唯一的。

我知道UNIQUE约束,但是我想知道是否有更好的方法进行检查。

我正在使用psycopg2运行查询,因此在偶然的机会上添加标签,那里有一些东西可以帮助解决这个问题。

如果列是唯一的,我可以添加一个约束。如果该列不是唯一列,则添加约束将返回错误

如果已经存在同名的约束,则返回有用的错误在这种情况下,宁愿只检查现有约束。

如果列是主键,则可以添加唯一约束而不会出现错误,但是在这种情况下,最好仅根据主键认识到列必须是唯一的。

下面的代码示例。

DROP TABLE IF EXISTS unique_test;
CREATE TABLE unique_test (
pkey INT PRIMARY KEY,unique_yes CHAR(1),unique_no CHAR(1)
);

INSERT INTO unique_test (pkey,unique_yes,unique_no)
VALUES(1,'a','a'),(2,'b','a');
    
CREATE UNIQUE INDEX CONCURRENTLY u_test_1  ON unique_test (unique_yes);

ALTER TABLE unique_test
ADD CONSTRAINT unique_target_1
UNIQUE USING INDEX u_test_1;

-- the above runs no problem

-- check what happens when column is not unique

CREATE UNIQUE INDEX CONCURRENTLY u_test_2  ON unique_test (unique_no);

ALTER TABLE unique_test
ADD CONSTRAINT unique_target_2
UNIQUE USING INDEX u_test_2;

-- returns:
-- sql Error [23505]: ERROR: Could not create unique index "u_test_2"
--  Detail: Key (unique_no)=(a) is duplicated.


CREATE UNIQUE INDEX CONCURRENTLY u_test_1  ON unique_test (unique_yes);

ALTER TABLE unique_test
ADD CONSTRAINT unique_target_1
UNIQUE USING INDEX u_test_1;

-- returns
-- sql Error [42P07]: ERROR: relation "unique_target_1" already exists


-- test what happens if adding constrint to primary key column

CREATE UNIQUE INDEX CONCURRENTLY u_test_pkey  ON unique_test (pkey);

ALTER TABLE unique_test
ADD CONSTRAINT unique_target_pkey
UNIQUE USING INDEX u_test_pkey;

-- this runs no problem but is inefficient.

解决方法

如果您只想要一个标志,可以使用:

select count(*) <> count(distinct uniq_no) as duplicate_flag
from unique_test;
,

如果您只想验证值是唯一的,请使用查询:

select unique_no,count(*)
  from unique_test
 group by unique_no
having count(*) > 1;

如果需要输出boolean

select not exists (
  select unique_no,count(*)
    from unique_test
   group by unique_no
  having count(*) > 1
);