在表格中我有3列:
id
tag1
tag2
id是主键。
我只想在该表中使用一个唯一的tag1-tag2组合。
例如,如果一个条目如下:
id: 1
tag1: cat
tag2: dog
我不希望插入下面的第二个条目:
id: 2
tag1: cat
tag2: dog
所以我制作了所有3列主键,但问题是第二个条目会被插入,因为它看起来是所有3个组合的组合。
我如何解决这个问题,以便只有tag1和tag2的组合是唯一的?
更新:我在tag1和tag2上添加了一个独特的约束。但是,它仍然可以插入:
id: 3
tag1: dog
tag2: cat
有没有办法阻止这种情况?
答案 0 :(得分:4)
您应该将ID作为主键,然后可以为tag1和tag2创建唯一约束:
ALTER TABLE my_table ADD CONSTRAINT uc_tags UNIQUE (tag1, tag2)
使用唯一约束,您将保证永远不会有两行具有重复的tag1和tag2值。
修改强>
除了上次更新之外,您无法使用唯一约束强制执行此更新。请记住,对于数据库,(tag1 = dog,tag2 = cat)的记录与(tag1 = cat,tag2 = dog)的记录完全不同。
可能最好的办法是重新设计数据库架构,如下所示:
- 表“tags”
- 表“消息”(或您正在标记的任何内容)
- 表“tags_messages”包含以下字段(message_id,tag_id)
然后,您只需将“tag_messages”表的(message_id,tag_id)设置为主键即可。这将自动强制执行不存在任何带有重复标记的消息。
一些示例数据:
Table: messages
message_id | title
-------------+------------------
1 | some message
2 | another message
Table: tags
tag_id | tags
-------------+-------------------
1 | cat
2 | dog
3 | duck
4 | horse
Table: messages_tags
message_id | tag_id
-------------+-------------------
1 | 1
1 | 2
2 | 3
2 | 4
2 | 1
答案 1 :(得分:1)
您可以将主键保留在“id”列中,并在“tag1”和“tag2”列上添加唯一约束。请参阅此link。
答案 2 :(得分:1)
添加一个结合了tag1和tag2的唯一索引。
答案 3 :(得分:1)
根据您是否以及何时需要在其他表中使用“唯一记录”,可以认为您的“id”字段是不必要的。 (这里的ID是代理键)如果您不在另一个表中使用“id”字段,那么将主键设置为(tag1,tag2)并删除“id”列真的更有意义在一起。
答案 4 :(得分:0)
我想问题是,你为什么这样做呢?了解商业原因会有所帮助。
您始终可以SELECT DISTINCT
仅获取具有唯一值的行。
答案 5 :(得分:0)
如果您可以控制插入和更新的顺序,则可以强制执行排列的唯一性:
alter table t23
add constraint tags_ck check (tag1 < tag2)
/
alter table t23
add constraint tags_uk unique (tag1, tag2)
/
这是有效的,因为检查约束拒绝('dog','cat')作为无效组合。因此,唯一约束可以确保只有evy一个记录具有标记的特定排列。
作为一种解决方案,这确实需要在插入和更新时进行一些干预,这可能足以为您提供此实现。我知道Oracle中使用基于函数的索引(我发布它here)的优雅解决方案,但我不认为MySQL支持类似的索引类型。