Sql 关于主键和唯一约束的帮助
在一个表中,我有3列:Sql 关于主键和唯一约束的帮助,sql,mysql,database-design,Sql,Mysql,Database Design,在一个表中,我有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
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
有什么方法可以防止这种情况发生吗?您应该保留ID作为主键,然后可以为tag1和tag2创建唯一的约束:
ALTER TABLE my_table ADD CONSTRAINT uc_tags UNIQUE (tag1, tag2)
使用unique约束,可以保证不会有两行具有重复的tag1和tag2值
编辑: 在上次更新之后,您无法使用唯一约束强制执行该更新。请记住,对于数据库,带有(tag1=dog,tag2=cat)的记录与带有(tag1=cat,tag2=dog)的记录完全不同 最好的办法可能是重新设计数据库架构,如下所示:
- 表“标签”
- 表“消息”(或您正在标记的任何内容)
- 带有以下字段的表“标记消息”(消息id、标记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
我想问题是,你为什么要这样做?了解业务原因会有所帮助
您可以始终
选择DISTINCT
,以仅获取具有唯一值的行 您可以将主键保留在“id”列上,并在“tag1”和“tag2”列上添加唯一约束。请参见此图。添加一个结合tag1和tag2的唯一索引
根据您是否以及何时需要在其他表中使用“唯一记录”,可以认为您的“id”字段是不必要的。(ID这里是一个代理键)如果您不在另一个表中使用“ID”字段,那么将主键设为(tag1,tag2)并一起删除“ID”列确实更有意义。如果您对插入和更新的顺序有一定的控制权,则可以强制执行排列的唯一性:
alter table t23
add constraint tags_ck check (tag1 < tag2)
/
alter table t23
add constraint tags_uk unique (tag1, tag2)
/
更改表t23
添加约束标记检查(tag1
这是因为check约束将('dog','cat')拒绝为无效组合。因此,唯一约束可以确保只有一条记录具有特定的标记排列
作为一种解决方案,这确实需要在插入和更新时进行一些干预,这可能足以让您接受此实现。我知道Oracle中有一个优雅的解决方案,它使用基于函数的索引(我发布了它),但我认为MySQL不支持类似类型的索引。对我来说,这似乎是一件完全合理的事情。我的许多表都有独特的约束。找到独特的价值观和确保它们是不一样的。我不知道你能做到……完美!请注意,与主键不同,每个表可以有许多
唯一的约束。如果我也希望忽略此项:id:3、tag1:dog、tag2:cat,该怎么办?我怎么能这么做?@noname:我现在明白你的意思了。不幸的是,您无法使用唯一的约束强制执行该操作。您必须稍微重新设计您的数据库模式以使其正常工作。您必须为标记创建一个单独的表,然后使用另一个表创建一个1对多关系。另一个表如何解决组合问题?很好,但我需要将它用于另一个表。1+注释:)可以争论,但前提是您不打算更改其他两个字段中的任何一个,并且永远不会添加使用此表主键的其他表。我将始终使用默认的代理键。否。但是,它们可以用于实现相同的功能。