【问题标题】:MySQL Unique Key scenarioMySQL 唯一键场景
【发布时间】:2014-09-10 23:02:11
【问题描述】:

我有一个由以下列组成的表格:

表名: 用户

列: {id, fk1, fk2, username}

id:是主键

fk1fk2 是来自其他表的外键

有两种情况:

1) fk1 + 用户名 = 唯一值

2) fk2 + 用户名 = 唯一值

例如:

fk1 = 国家表中国家的id

fk2 = 状态表中状态的id

在有州的国家(例如美国)

我想要的是用户的用户名只在一个状态内是唯一的。来自不同州的两个用户可以拥有相同的用户名,但不能处于同一州。

在没有州的国家(例如西班牙)

来自同一国家的两个用户不能使用相同的用户名。来自不同国家的两个用户可以使用相同的用户名。

所以,如果注册的用户来自一个有州的国家,我需要为列 fk2username 创建一个唯一索引。 [确保每个状态的唯一性]

如果注册的用户来自没有州的国家,我需要为列 fk1username 创建唯一索引。 [确保每个国家/地区的唯一性]

到目前为止,我所做的是为来自州的用户创建一个表,为来自没有州的国家/地区的用户创建一个表。如下:

--表名:User_States

列:{id, fk2, username}

fk2 + 用户名上的唯一索引

--表名:用户

列:{id, fk1, username}

fk1 + 用户名上的唯一索引

此解决方案可以通过在将数据插入每个表之前过滤用户(来自状态或非状态的用户)来工作。但是我只想要一个包含所有用户的表,而不是两个,因为当我想检查例如电子邮件是否已被用户注册(无论是否处于状态)时,我必须执行 2 个查询(每个表中一个)。或者,如果我想提取所有用户名(如“darklord”)的列表,无论其位置如何,我都必须再次执行 2 次查询。

有没有办法做到这一点?如果是,表格会是什么样子?当用户来自没有州的国家时,我的问题就开始了,因为 fk2 列将是空的。我知道唯一索引允许 Null 值,但只允许一个 Null 值。

还有一个一般性问题:如何检查大表上的单个查询是否比 2 个小表上的 2 个查询快/慢?

PS:我使用的存储引擎是InnoDB

提前致谢。

【问题讨论】:

  • 为什么你会允许这种类型的准唯一用户名?当一个人登录时,他们必须输入他们的用户名、密码和位置信息吗?如果您有 2 个人使用相同的用户名和相同的密码会发生什么?哪一个?这就是用户名独一无二的原因。
  • “用户名”只是一个例子——而且可能是一个不好的例子。试着把它想象成一个数据字段,多个用户可以有相同的值,但与 fk1 或 fk2 链接是唯一的,如上所述。
  • 你能用一个表而不是多个表来保存这些值吗?然后,您可以在多个列上使用唯一约束。
  • 将表拆分为Country表和State表的原因是为了(在一定程度上)满足规范化。想象一下,如果我有 10.000 个来自西班牙的用户.. “西班牙”这个词将在我的数据库中重复 10.000..
  • 如果您正确规范化数据,则不会。您应该有一个 Country 表,并且将 CountryCode(如果使用自然键)或身份值(如果使用代理键)存储在该表中。

标签: php mysql sql sql-server database


【解决方案1】:

这样的作品?

create table #Something
(
    SomeDataField varchar(10) not null,
    CountryCode char(3) not null,
    StateCode char(2) null,
    CONSTRAINT UniqueCountryState UNIQUE NONCLUSTERED
    (
        SomeDataField, CountryCode, StateCode
    )
)

insert #Something
select 'Value1', 'USA', 'NY' union all
select 'Value1', 'CAN', null union all
select 'Value1', 'MEX', null union all
select 'Value1', 'USA', 'AK'

现在尝试再次插入这些值中的任何一个,它将会失败,因为该组合已经存在。

insert #Something
select 'Value1', 'USA', 'NY'

【讨论】:

  • 今晚我会试一试,然后告诉你。我试图通过使用唯一索引来限制它,我可以使用服务器端的 PHP 脚本来限制它。我需要唯一键的原因是为了更快的数据搜索..
  • 我强烈建议您不要将引用完整性留给应用程序。使用应用程序来提供帮助并没有错,但将其从数据库中删除是灾难的根源。顺便说一句,我不知道我发布的代码是否适合您,因为您使用的是 InnoDB,而我发布的代码是 sql server。我对 InnoDB 一无所知。
  • 而且快速搜索不需要唯一键。唯一约束将在后台生成一个索引,这将有助于您在查询数据时的性能。您可以添加索引而无需唯一约束。
  • 别担心。我需要的只是它背后的想法,我也会让它在 MySQL 中工作。
  • 大声思考,如果在非状态用户的情况下,我添加了 fk2 = 0 [或 fk2 DEFAULT VALUE '0'],然后在 fk1+fk2+SomeDataField 上只创建了一个唯一索引?这样,唯一键对于两种情况都应该始终是唯一的。而在州用户的情况下插入对应的fk2。如果纽约的id为2,则fk2=2,美国的id为6,则fk1=6,则其将插入6 1 SomeData。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-08-20
  • 2011-01-26
  • 1970-01-01
  • 1970-01-01
  • 2014-01-12
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多