MySQL和UNIQUE专栏:如何避免重复?

时间:2017-03-29 13:14:19

标签: php mysql sql database indexing

我有一个包含以下列的表:

(id, col_1, col_2)

其中“id”是主键(auto-inc)。

我想将col_1col_2设为“唯一组合”。

对于示例,如果我插入数据......

(.., col_1, col_2 ) = (.., 'A', 'B') 

...接下来,我不允许插入以下内容:

(.., col_1, col_2 ) = (.., 'A', 'B')
(.., col_1, col_2 ) = (.., 'B', 'A') #because it already exists, in another order:('A','B')   

我使用UNIQUE(col_1, col_2) ...

成功阻止了第一个案例

似乎允许“反向组合” (.., 'B', 'A')

我该怎么办?

2 个答案:

答案 0 :(得分:1)

尝试之后,实际上并不像创建另一个独特的索引那么容易 这似乎是MySQL的一个奇怪的缺陷。解决方法虽然可以始终在col_1中存储较小的值,在col_2中存储较大的值(当您不喜欢触发器时):

INSERT INTO your_table (col_1, col_2) VALUES (LEAST('A', 'B'), GREATEST('A', 'B'));

您可以找到这些功能的文档here

答案 1 :(得分:1)

正如fancyPants所说,解决方案是确保一列始终低于另一列。 MySQL不支持CHECK约束,但您可以使用触发器强制执行此操作,这将允许您捕获应用程序错误:

Can a MySQL trigger simulate a CHECK constraint?

注意:根据MySQL版本,使用触发器引发错误将使用不同的方法。

在较新的MySQL版本中,您还可以创建虚拟列并对其进行索引。也许你可以创造一个独特的(最少(a,b),最大(a,b))......但它会有点笨拙。

此外,知道< = b是约束将加速搜索。如果你需要搜索(x,y)或(y,x),那么你知道表中唯一的一个是正确的顺序,这简化了你的WHERE并使索引使用得更好。