可延迟、不区分大小写的唯一约束

问题描述 投票:0回答:1

PostgreSQL 是否可以在字符列上创建可延迟的唯一约束,但不区分大小写?

我们假设以下基本表:

CREATE TABLE sample_table ( 
   my_column VARCHAR(100)
);

如果不需要可延迟约束,就像用函数创建唯一索引一样简单,例如:

CREATE UNIQUE INDEX my_unique_index ON sample_table(UPPER(my_column));

延迟约束检查需要显式创建约束,例如:

ALTER TABLE sample_table 
 ADD CONSTRAINT my_unique_constraint UNIQUE(my_column)
 DEFERRABLE INITIALLY IMMEDIATE;

不幸的是,不可能在唯一约束中使用任意函数。

一种可能的解决方法是创建与

my_column
内容相同但大写的附加列,在每次更新/插入后通过触发器进行更新,然后在此人工列上创建可延迟的唯一约束。然而,这听起来像是一个非常丑陋的黑客。

或者,应该可以使用

CREATE CONSTRAINT TRIGGER
并手动检查不区分大小写的唯一性(当然,常规索引仍然是必要的)。对于这样一个简单(我认为也是流行的)要求来说,这听起来有点过于复杂。

有没有更简单和/或更优雅的方法来解决这个限制?
我现在使用的是 Postgres 9.1。但欢迎更新的解决方案。

postgresql constraints case-insensitive database-indexes
1个回答
23
投票

您可以使用同名附加模块提供的特殊类型

citext
来规避限制。引用手册:

citext
模块提供了不区分大小写的字符串类型, citext。本质上,它在比较值时在内部调用 lower。 否则,它的行为几乎与
text
完全相同。

它准确地解决了您的情况。每个数据库运行一次:

CREATE EXTENSION citext;

然后你可以:

CREATE TABLE sample_table ( 
  my_column citext
, CONSTRAINT my_unique_constraint UNIQUE(my_column) DEFERRABLE INITIALLY IMMEDIATE
);
© www.soinside.com 2019 - 2024. All rights reserved.