2009-05-06 60 views
3

我有套设置用户表,它有以下栏目:SQL:主键还是不主键?

UserID INT 
Set VARCHAR(50) 
Key VARCHAR(50) 
Value NVARCHAR(MAX) 
TimeStamp DATETIME 

用户名与SET键和键一起是唯一的。因此,特定用户不能在特定的一组设置中拥有两个相同的密钥。这些设置是通过set来检索的,所以如果用户请求某个特定集合中的某个特定的密钥,那么整个集合将被下载,以便下一次需要来自同一集合的密钥时,它不必访问数据库。

我应该在所有三列(userid,set和key)上创建一个主键还是应该创建一个具有主键的额外字段(例如一个名为SettingID的自动增量整数,我想是坏主意),或者不创建主键,只创建一个唯一的索引?

----- ----- UPDATE

只是为了澄清一些事情:这是行表的末端,这是无论如何也不能加入。用户ID是用户表的FK。 Set不是FK。它几乎是我的GUI的帮助表。举个例子:用户第一次访问网站的某些部分时,可以找到一个帮助气球,如果他们想要的话,他们可以关闭它。一旦他们点击它,我会添加一些设置到“GettingStarted”设置,它将声明他们helpballoon X已被禁用。下次用户进入同一页面时,该设置将声明帮助气球X不应再显示。

+0

你说这是一个“设置”表。我们可以假设这张表是一个“行尾”表,并且你在这个表中的关键字不会被用作任何其他表中的外键? – Jonathan 2009-05-06 08:39:45

+0

小心:您在概念上仍然有一个连接:与GUI的连接。因此,拥有自然主键的风险可能仍然适用。 – 2009-12-22 07:52:20

回答

2

我应该建立在所有三列的主键(userid, set, and key)

让这一个。

使用代理主键将导致一个额外的列不用于其他目的。

与代理主键一起创建UNIQUE INDEX与创建非集群PRIMARY KEY相同,并且会导致额外的KEY lookup,这对性能来说更糟糕。

创建UNIQUE INDEX而不使用PRIMARY KEY将导致HEAP-organized表需要额外的RID lookup来访问值:也不是很好。

7

具有复合独特的键大多不是一个好主意。

任何业务相关的数据作为主键也可以让你麻烦。例如,如果您需要更改值。如果在应用程序中无法更改该值,则可能会在将来使用,或者必须在升级脚本中对其进行更改。

最好是创建一个代理键,这是一个自动编号,它没有任何商业意义。

编辑您更新后:

在这种情况下,你可以认为有概念上没有主键,并使这三列,列复合唯一键的主键(使它多变)。

+1

是的。想象一下复合关键情况可能出现的以下问题。如果密钥中的某些数据需要更改,会发生什么情况?如果你需要加入这张桌子怎么办?然后,您需要复制连接表 – 2009-05-06 08:32:49

0

我可能会尝试确保UserID是唯一标识符,而不是在整个代码中都有重复的UserID。复合键往往会在你的代码的生命中变得混乱。

我假设这是某种配置值的查找字段,所以如果是这种情况,您可以使用组合键。数据已经存在。您可以使用主键保证它的唯一性。如果您改变主意并稍后决定不适合您,则可以轻松添加SettingId并将原始组合键设为唯一索引。

0

创建一个独立的主键。无论bussines逻辑如何变化,必须对您的Key VARCHAR(50)字段应用哪些新规则 - 拥有一个主键将使您完全独立于bussines逻辑。

0

根据我的经验,这一切都取决于有多少表将使用此表作为FK信息。你是否想在其他表格中增加3个额外的列,以便携带FK?

就我个人而言,我会创建另一个FK列,并将其他三列的唯一约束。这使得这张表的外键更容易被吞下。

0

更好地将UserID设置为32位newid()或唯一标识符,因为UserID作为int向用户提供可能的UserID的提示。这也将解决您的复合密钥问题。

1

你有多少个Key和Set?这些需要是varchar(50)还是可以指向查找表?如果您可以将此Set和Key转换为SetId和KeyId,那么您可以在3个整数值上创建主键,这将会快得多。

0

我不是组合键的支持者,但在这种情况下,作为行表的结尾,它可能是有道理的。但是,如果您允许在这三个字段中的任何一个字段中出现空值,因为在插入时一个或多个值未知,可能会有困难,并且唯一索引可能会更好。