可延迟、不区分大小写的唯一约束
Posted
技术标签:
【中文标题】可延迟、不区分大小写的唯一约束【英文标题】:Deferrable, case-insensitive unique constraint 【发布时间】:2013-05-30 03:25:30 【问题描述】:在 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
内容相同但大写的附加列,在每次更新/插入后通过触发器进行更新,然后在此人工列上创建可延迟的唯一约束。然而,这听起来像一个非常丑陋的 hack。
或者,应该可以使用CREATE CONSTRAINT TRIGGER
并手动检查不区分大小写的唯一性(当然仍然需要常规索引)。对于如此简单(我想也很流行)的要求,这听起来有点过于复杂了。
有没有更简单和/或更优雅的方法来解决这个限制?
【问题讨论】:
你的 Postgres 版本? 目前是 9.1。但是,如果在较新的版本上有一个不错的解决方案,我会非常乐意阅读它:) 检查EXCLUDE
约束。它们可以设置为不区分大小写的UNIQUE
。
+1 非常有趣的问题!
@Igor 谢谢,这很有趣——我不知道EXCLUDE
的限制(可能没有花足够的时间处理 9.x 文档)。我发现它在其他情况下也非常有用。
【参考方案1】:
您可以通过使用由同名附加模块提供的特殊类型citext
来规避限制。引用手册:
citext
模块提供了不区分大小写的字符串类型, 文案。本质上,它在比较值时在内部调用 lower。 否则,它的行为几乎与text
完全相同。
它完全解决了您的情况。每个数据库运行一次:
CREATE EXTENSION citext;
那么你可以:
CREATE TABLE sample_table (
my_column citext
,CONSTRAINT my_unique_constraint UNIQUE(my_column)
DEFERRABLE INITIALLY IMMEDIATE
);
【讨论】:
太好了,这正是我在这种情况下想要的(仍然希望有一些解决方案允许在约束中发挥作用;))。对于 Ubuntu 用户 -citext
在 postgresql-contrib
包中。
我不应该添加扩展来使字符串类型不区分大小写...... postgress 应该提供更好的解决方案
@Leonel:您的意见得到了适当的注意。不过,不确定它如何转化为对我的回答的反对。如果您有特定的问题要解决,请考虑发布问题,有多种情况可以在不安装扩展程序citext
的情况下解决。但是安装它并没有错,这实际上只是CREATE EXTENSION citext;
的问题。该模块是发行版的一部分,由同一个团队维护和发布,并进行了彻底的测试。它不在核心版本中的唯一原因是大多数人不需要它。它是“Postgres”,顺便说一句,是 PostgreSQL 的缩写。
您对citext
与unique
约束一起使用时的实际性能开销有何看法?因为它似乎在内部调用了 C str_tolower()
:***.com/questions/31133603/…。以上是关于可延迟、不区分大小写的唯一约束的主要内容,如果未能解决你的问题,请参考以下文章