Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/postgresql/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 在Postgres的单个索引中包含多个列_Sql_Postgresql_Indexing - Fatal编程技术网

Sql 在Postgres的单个索引中包含多个列

Sql 在Postgres的单个索引中包含多个列,sql,postgresql,indexing,Sql,Postgresql,Indexing,我有一个“用户”表,有两列,“email”和“new_email”。我需要: 覆盖两列的不区分大小写的唯一性约束-即if“Bob@Example.com显示在一行的“电子邮件”列中,然后插入bob@example.com“插入另一行(甚至同一行)“新建电子邮件”列时应失败 在“email”或“new_email”字段中快速搜索给定的电子邮件地址,不区分大小写-即查找新_email或email所在的行“Bob@example.com“,不区分大小写 我知道通过创建一个相关的“emails”表,

我有一个“用户”表,有两列,“email”和“new_email”。我需要:

  • 覆盖两列的不区分大小写的唯一性约束-即if“Bob@Example.com显示在一行的“电子邮件”列中,然后插入bob@example.com“插入另一行(甚至同一行)“新建电子邮件”列时应失败

  • 在“email”或“new_email”字段中快速搜索给定的电子邮件地址,不区分大小写-即查找新_email或email所在的行“Bob@example.com“,不区分大小写

我知道通过创建一个相关的“emails”表,我可以更容易地做到这一点,但我希望在这个表中查找来自多个应用程序的用户(通过主键),并且我希望避免在不同的地方重复连接逻辑来检索他们的电子邮件。所以如果可能的话,我认为某种表达式索引是最好的

如果这是不可能的,我想我的下一个最佳选择是创建一个视图,其他应用程序可以使用该视图轻松获取用户的电子邮件以及其他信息,但我也不知道如何做到这一点


我用的是Postgres 8.4。谢谢大家!

我认为您必须使用触发器来强制执行跨列唯一性约束。如果在每列上添加唯一的索引,然后触发类似的事件(未在我的头代码顶部测试):

您可能需要这样的东西作为插入前和更新前触发器。该触发器将负责捕获跨列重复项,而唯一索引将负责列内重复项

一些有用的参考资料:

不管怎样,您都需要查询的单个索引,并且使用索引的唯一性一半简化了触发器,只处理跨列部分;如果您试图在触发器中完成所有操作,则必须注意在不真正更改
email
email\u new
列的情况下更新行


对于查询的一半,您可以使用一个来组合这两个列。您还可以创建一个函数,将用户的电子邮件地址合并到一个列表中。如果不知道这些其他查询的更多细节,很难说哪一个是最好的,但我怀疑修复所有其他查询以了解
email
email\u new
将是最好的方法;您必须更新所有其他查询才能使用视图或函数,那么为什么要构建视图或函数呢?

不需要触发器。试试这个:

create  table et (email text, email2 text);
create unique index et_u on et (coalesce(lower(email),lower(email2)));
insert into et (email,email2) values ('scott@gmail.com',NULL);
insert into et (email,email2) values ('scott@gmail.com',NULL);
ERROR:  duplicate key value violates unique constraint "et_u"
insert into et (email,email2) values (NULL,'scott@gmail.com');
ERROR:  duplicate key value violates unique constraint "et_u"
insert into et (email,email2) values (NULL,'Scott@gmail.com');
ERROR:  duplicate key value violates unique constraint "et_u"

嗯,这并不完美,我可以同时在两个字段中输入相同的电子邮件。因此,您还需要一个检查约束,该约束在此处通过Email2发送。更改表格et添加约束et_nn检查(Email2);那很有趣。Postgres是否足够聪明,可以在查询电子邮件地址时使用该索引?例如
其中较低(电子邮件)='scott@gmail.com“
?或者有没有另一种方法可以对查询进行短语化以使其执行此操作?如果插入
(NULL,'xx@example.com)
然后
('yy@example.com','xx@example.com“)
当没有yy@example.com"到目前为止,,当
电子邮件
不为空时,合并有效地隐藏了
电子邮件2
的唯一性检查。两个小写的
唯一索引
函数和一个表检查是最好的选择。没有必要调用触发器来解决此问题。使用下面@Scott建议的派生方法。@Sean:Scott的解决方案很好,但合并会留下漏洞。同意,我不会使用
COALESCE
或两列在单个表中存储旧值和当前值。
create  table et (email text, email2 text);
create unique index et_u on et (coalesce(lower(email),lower(email2)));
insert into et (email,email2) values ('scott@gmail.com',NULL);
insert into et (email,email2) values ('scott@gmail.com',NULL);
ERROR:  duplicate key value violates unique constraint "et_u"
insert into et (email,email2) values (NULL,'scott@gmail.com');
ERROR:  duplicate key value violates unique constraint "et_u"
insert into et (email,email2) values (NULL,'Scott@gmail.com');
ERROR:  duplicate key value violates unique constraint "et_u"