两列组合的双向唯一键约束

use*_*234 5 mysql mariadb

我在MySQL中有以下表格列.

id
user_primary_email
user_secondary_email
Run Code Online (Sandbox Code Playgroud)

我希望通过使用我可以实现的列user_primary_emailuser_secondary_email唯一的组合UNIQUE KEY unique_key_name (user_primary_email, user_secondary_email)

上面添加的唯一键约束将帮助我实现以下场景,或者仅通过向单个列本身添加唯一键.

user_primary_email = 'xyz@gmail.com' AND user_secondary_email = 'pqr@gmail.com'
user_primary_email = 'xyz@gmail.com' AND user_secondary_email = 'pqr@gmail.com' //This will not be allowed to enter due to unique key constraint
Run Code Online (Sandbox Code Playgroud)

现在我遇到的问题是不应该允许以相反的方式添加相同的组合,如下所述.

user_primary_email = 'pqr@gmail.com' AND user_secondary_email = 'xyz@gmail.com' //This should not be allowed to add since already same email id combination added once

id    |   user_primary_email   |   user_secondary_email
-------------------------------------------------------
1     |   xyz@gmail.com        |   pqr@gmail.com
-------------------------------------------------------
2     |   pqr@gmail.com        |   xyz@gmail.com       
-------------------------------------------------------
Run Code Online (Sandbox Code Playgroud)

在插入行id 2期间的上述情况中,它应该抛出错误,因为电子邮件ID组合已经在行id 1中使用.

任何帮助都会很棒.

Sol*_*are 5

对此没有直接支持,但您可以使用解决方法来创建双向密钥:您需要在两列的有序版本上有一个唯一的密钥。

幸运的是,您可以轻松做到这一点。MySQL 5.7.6+ 支持生成列及其唯一索引,您可以使用它们对两个值进行排序并强制唯一性。

create table testBiDirKey (
  a varchar(100), 
  b varchar(100),
  a_ordered varchar(100) as (least(a, b)) STORED,
  b_ordered varchar(100) as (greatest(a, b)) STORED,
  unique key unqBi_test_ab (a_ordered, b_ordered)
);

insert into testBiDirKey(a,b) values('a', 'b');
insert into testBiDirKey(a,b) values('b', 'a');
Error Code: 1062. Duplicate entry 'a-b' for key 'unqBi_test_ab'
Run Code Online (Sandbox Code Playgroud)

这将null完全视为您当前的正常唯一密钥,因此

insert into testBiDirKey(a,b) values('a', null);
insert into testBiDirKey(a,b) values('a', null);
insert into testBiDirKey(a,b) values(null, 'a');
Run Code Online (Sandbox Code Playgroud)

都是允许的。如果需要,您可以添加coalesce(x,'')为仅允许一个空值(或null) 。''如果您在添加值之前验证它们(例如,如果它们不包含,),则可以将两列合并为一列,并用 - 连接,- 尽管除了仅增加 1 列之外几乎没有什么好处。

对于 5.7.8+,您不再需要STORED关键字即可在索引中使用这些列。如果值被存储(使用磁盘空间)或在需要时计算(默认),则该关键字会起作用。

在 MySQL 5.7.6 之前,您可以使用触发器( onupdateinsert)用这些值更新两列,应用相同的逻辑,只是多了一点代码。


ele*_*nst 5

在任何MariaDB中:

CREATE TABLE `t` (
  `id` int(11) NOT NULL,
  `user_primary_email` varchar(64) DEFAULT NULL,
  `user_secondary_email` varchar(64) DEFAULT NULL,
  `mycheck` varchar(128) AS (IF(user_primary_email<user_secondary_email,CONCAT(user_primary_email,user_secondary_email),CONCAT(user_secondary_email,user_primary_email))) PERSISTENT,
  PRIMARY KEY (`id`),
  UNIQUE KEY `mycheck` (`mycheck`)
);

MariaDB [test]> insert into t values (1,'a','b',null);
Query OK, 1 row affected (0.03 sec)

MariaDB [test]> insert into t values (2,'b','a',null);
ERROR 1062 (23000): Duplicate entry 'ab' for key 'mycheck'
Run Code Online (Sandbox Code Playgroud)