Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/83.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 关于主键和唯一约束的帮助_Sql_Mysql_Database Design - Fatal编程技术网

Sql 关于主键和唯一约束的帮助

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上添加了一个唯一的约束。但是,仍然

在一个表中,我有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

有什么方法可以防止这种情况发生吗?

您应该保留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)
然后您可以简单地将“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

我想问题是,你为什么要这样做?了解业务原因会有所帮助


您可以始终
选择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+注释:)可以争论,但前提是您不打算更改其他两个字段中的任何一个,并且永远不会添加使用此表主键的其他表。我将始终使用默认的代理键。否。但是,它们可以用于实现相同的功能。