2011-01-12 35 views
1

比方说,我有一个通用的内容管理系统,其中保存了一个节点表(具有关联权限的导航点)以及每种节点(博客文章,评论,附件等)的表格。什么时候应该给一个SQL表格自己的数字主键?

我的节点表(在MySQL)看起来像这样:

CREATE TABLE node_types (
    type_id INT PRIMARY KEY AUTO_INCREMENT, 
    type_parent INT, 
    type_name VARCHAR(31) UNIQUE KEY, 

    FOREIGN KEY (type_parent) REFERENCES node_types(type_id) 
) ENGINE = InnoDB; 

CREATE TABLE nodes (
    node_id INT PRIMARY KEY AUTO_INCREMENT, 
    type_id INT, 
    parent_id INT, 

    FOREIGN KEY (type_id) REFERENCES node_types (type_id), 
    FOREIGN KEY (parent_id) REFERENCES nodes (node_id) 
) ENGINE = InnoDB; 

然后创建不同类型的节点,我做这样的事情:

CREATE TABLE attachments (
    node_id INT PRIMARY KEY, 
    attachment_filename VARCHAR(255), 
    attachment_title VARCHAR(255), 

    FOREIGN KEY (node_id) REFERENCES nodes (node_id) 
) ENGINE = InnoDB; 
INSERT INTO node_types (type_name) VALUES ('attachment'); 

使用这种方法,我可以开发一种普通权限系统适用于节点,而无需通过引用node_id将其专用于所有不同的节点类型。

在这种情况下,我没有为附件提供“自己的”数字主键,因为附件是与节点1:1关系的节点 - 其主键基于node_id。但有些人会/做。附件表可以很容易地改写为:

CREATE TABLE attachments (
    attachment_id INT PRIMARY KEY, 
    node_id INT UNIQUE NOT NULL, -- a node is-a attachment. 
    attachment_filename VARCHAR(255), 
    attachment_title VARCHAR(255) 

    FOREIGN KEY (node_id) REFERENCES nodes (node_id) 
) ENGINE = InnoDB; 
INSERT INTO node_types (type_name) VALUES ('attachment'); 

你认为什么是重要的原因,为什么不能一会放给一个数字唯一的主键ID到表?特别是,我觉得我有时与“没有为具有1:!is-a关系的表分配主键”的业务不一致。

回答

0

如果您有一个子表(即具有指向该表的外键的表),则最有可能要在父表上创建一个主键。

如果你有一个“叶桌”,它并不是真的有必要。但是,仍然有一个很好的做法。如果由于网站和用户创建包含叶表中记录链接的书签而仍然希望访问它,那么您最有可能还想在此处添加主键。

换句话说,它确实取决于。

+0

为什么它会是一个好习惯,顺便说一句?如果我在附件上创建主键,是否有任何优势? – user572491 2011-01-12 10:35:09

+0

@ user572491:这就是为什么我说“它*可能是一个很好的做法”。这取决于你和谁交谈以及你喜欢什么。 - 关于优点:如果您不需要任何逻辑中的该列,则没有优势,实际上它会消耗更多空间。但是,如果在某个时候需要添加额外的逻辑需要这样一个ID,那么您要么已经拥有了它,要么需要相应地更新您的表结构,这可能会导致副作用。 - 正如我所说,这真的取决于。 – sjngm 2011-01-12 10:56:09

0

那么,如果这将永远是1:1的关系,你的方式应该工作。

不应该有任何困难的理由使用不同的uniqe编号的附件。

0

我会离开它,因为你目前拥有它。引入额外的数字ID似乎是混淆的秘诀 - 如果您正在寻找附件11375,那么它的attachment_id或其node_id?

作为一般性建议,我建议您最多只有一个在任何表上声明的代理键,以及实际存在的许多实际键。代理键是一个数字键(例如int),当没有真正的键适合包含在索引,FK引用等中时,使用该键,例如是varchar列或(取决于具体情况)跨度多列。

相关问题