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

Cod*_*ers 15 postgresql constraints database-indexes

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

我们假设以下基本表:

CREATE TABLE sample_table ( 
   my_column VARCHAR(100)
);
Run Code Online (Sandbox Code Playgroud)

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

CREATE UNIQUE INDEX my_unique_index ON sample_table(UPPER(my_column));
Run Code Online (Sandbox Code Playgroud)

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

ALTER TABLE sample_table 
 ADD CONSTRAINT my_unique_constraint UNIQUE(my_column)
 DEFERRABLE INITIALLY IMMEDIATE;
Run Code Online (Sandbox Code Playgroud)

遗憾的是,不可能在唯一约束中使用任意函数.

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

或者,应该可以使用CREATE CONSTRAINT TRIGGER并手动检查不区分大小写的唯一性(当然,仍然需要常规索引).对于如此简单(以及流行的,我认为)的要求,这听起来有点过于复杂.

围绕这个限制是否有更简单和/或更优雅的方式?

Erw*_*ter 15

您可以使用citext同名附加模块提供的特殊类型来规避限制.引用手册:

citext模块提供不区分大小写的字符串类型citext.从本质上讲,它在比较值时内部调用较低.否则,它的行为几乎完全一样text.

它完全解决了你的情况.每个数据库运行一次:

CREATE EXTENSION citext;
Run Code Online (Sandbox Code Playgroud)

然后你可以:

CREATE TABLE sample_table ( 
   my_column citext
  ,CONSTRAINT my_unique_constraint UNIQUE(my_column)
   DEFERRABLE INITIALLY IMMEDIATE
);
Run Code Online (Sandbox Code Playgroud)

  • @Leonel:你的意见得到了适当的注意.但是不确定它是如何转换为我的答案的downvote.如果你有一个特定的问题要解决,考虑发一个问题,有各种情况可以解决,而无需安装扩展名`citext`.但是安装它并没有什么不妥,这只是"CREATE EXTENSION citext"的问题.该模块是分发的一部分,由同一团队维护和发布,并经过全面测试.它不在核心版本中的唯一原因是因为大多数人不需要它.这是"Postgres",顺便说一句,是PostgreSQL的缩写. (7认同)
  • 我不应该添加扩展名来具有不区分大小写的字符串类型... postgress应该提供更好的解决方案 (2认同)