【问题标题】:Bi-directional unique key constraint for combination of two columns两列组合的双向唯一键约束
【发布时间】:2017-04-23 17:52:23
【问题描述】:

我在 MySQL 中有下表列。

id
user_primary_email
user_secondary_email

我想让列 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

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

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

在上述情况下,在插入 row id 2 期间,它应该会抛出错误,因为这两个电子邮件 id 组合都已在 row id 1 中使用。

任何帮助都会很棒。

【问题讨论】:

  • 这在这种情况下不起作用。
  • 啊,对不起,我不确定 mysql。我知道在 sql server 中你可以编写一个函数,其中有一个查询,可以放在一个检查约束中......我猜 mysql 不存在同样的情况?

标签: mysql mariadb


【解决方案1】:

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

幸运的是,您可以很容易地做到这一点。 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'

这会将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');

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

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

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

【讨论】:

  • 很好的答案和清晰的解释......我正在使用 MariaDB,因此接受上述答案......但也支持你的答案,因为这对其他人非常有帮助......谢谢跨度>
【解决方案2】:

在任何 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'

【讨论】:

    猜你喜欢
    • 2012-05-17
    • 1970-01-01
    • 2013-03-25
    • 1970-01-01
    • 1970-01-01
    • 2020-01-06
    • 2011-03-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多