简体   繁体   English

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

[英]Bi-directional unique key constraint for combination of two columns

I have the below table columns in MySQL. 我在MySQL中有以下表格列。

id
user_primary_email
user_secondary_email

I want to make the combination of columns user_primary_email and user_secondary_email unique which I can achieve by using UNIQUE KEY unique_key_name (user_primary_email, user_secondary_email) 我想通过使用UNIQUE KEY unique_key_name (user_primary_email, user_secondary_email)来实现user_primary_emailuser_secondary_email列的唯一组合。

The above addition of unique key constraint will help me achieve the below scenario or rather just by adding a unique key to the individual column itself. 上面添加的唯一键约束将帮助我实现以下场景,或者仅通过向单个列本身添加唯一键。

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

Now the problem which I am facing is the same combination should not be allowed to add in a reverse way as mentioned below. 现在我遇到的问题是不应该允许以相反的方式添加相同的组合,如下所述。

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       
-------------------------------------------------------

In the above case during insert of row id 2 it should throw error as both the email id combination is already used in row id 1 . 在插入行id 2期间的上述情况中,它应该抛出错误,因为电子邮件ID组合已经在行id 1中使用

Any help would be great. 任何帮助都会很棒。

In any MariaDB: 在任何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'

There is no direct support for that, but you can use a workaround to create your bidirectional key: You need a unique key on an ordered version of your two columns. 没有直接支持,但您可以使用变通方法来创建双向密钥:您需要在两列的有序版本上使用唯一密钥。

Fortunately, you can very easily do that. 幸运的是,你可以很容易地做到这一点。 MySQL 5.7.6+ supports generated columns and unique indexes for them, which you can use to order your two values and to enforce uniqueness. 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'

This will treat null exactly as your current normal unique key, so 这将把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');

are all allowed. 都是允许的。 You can add coalesce(x,'') to only allow one empty value (either null OR '' ) if you want. 如果需要,可以添加coalesce(x,'')以仅允许一个空值( null OR '' )。 If you verify your values before you add them (eg if they don't contain a , ), you can combine the two columns to just one, concatenated with an , - although with little benefit apart from just having 1 additional column. 如果在添加它们之前验证了它们的值(例如,如果它们不包含a , ),您可以将两列合并为一列,与a连接,但除了只有一个额外的列之外几乎没什么好处。

For 5.7.8+, you don't need the STORED keyword anymore to be able to use these columns in an index. 对于5.7.8+,您不再需要STORED关键字才能在索引中使用这些列。 That keyword effects if the values are stored (using disk space) or calculated when required (default). 如果值存储(使用磁盘空间)或在需要时计算(默认),则该关键字会生效。

Before MySQL 5.7.6, you can use a trigger (on update and insert ) to update the two columns with the these values, the same logic applies, it's just a little more code. 在MySQL 5.7.6之前,您可以使用触发器(在updateinsert )使用这些值更新两列,同样的逻辑适用,它只是一些代码。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM