数据库设计和非数字主键的使用

Nic*_*ngs 14 sql database database-design primary-key primary-key-design

我目前正在为客户和网站管理应用程序设计数据库表.我的问题是关于使用主键作为表的功能部分(并没有为每个表分配"ID"号).

例如,以下是目前为止数据库中的四个相关表,其中一个表使用传统的主键号,其他表使用唯一的名称作为主键:

--
-- website
--
CREATE TABLE IF NOT EXISTS `website` (
  `name` varchar(126) NOT NULL,
  `client_id` int(11) NOT NULL,
  `date_created` timestamp NOT NULL default CURRENT_TIMESTAMP,
  `notes` text NOT NULL,
  `website_status` varchar(26) NOT NULL,
  PRIMARY KEY  (`name`),
  KEY `client_id` (`client_id`),
  KEY `website_status` (`website_status`),
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

--
-- website_status
--
CREATE TABLE IF NOT EXISTS `website_status` (
  `name` varchar(26) NOT NULL,
  PRIMARY KEY  (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
INSERT INTO `website_status` (`name`) VALUES
('demo'),
('disabled'),
('live'),
('purchased'),
('transfered');

--
-- client
--
CREATE TABLE IF NOT EXISTS `client` (
  `id` int(11) NOT NULL auto_increment,
  `date_created` timestamp NOT NULL default CURRENT_TIMESTAMP,
  `client_status` varchar(26) NOT NULL,
  `firstname` varchar(26) NOT NULL,
  `lastname` varchar(46) NOT NULL,
  `address` varchar(78) NOT NULL,
  `city` varchar(56) NOT NULL,
  `state` varchar(2) NOT NULL,
  `zip` int(11) NOT NULL,
  `country` varchar(3) NOT NULL,
  `phone` text NOT NULL,
  `email` varchar(78) NOT NULL,
  `notes` text NOT NULL,
  PRIMARY KEY  (`id`),
  KEY `client_status` (`client_status`)
) ENGINE=InnoDB  DEFAULT CHARSET=latin1 AUTO_INCREMENT=4 ;

--
-- client_status
---
CREATE TABLE IF NOT EXISTS `client_status` (
  `name` varchar(26) NOT NULL,
  PRIMARY KEY  (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

INSERT INTO `client_status` (`name`) VALUES
('affiliate'),
('customer'),
('demo'),
('disabled'),
('reseller');
Run Code Online (Sandbox Code Playgroud)

如您所见,4个表中的3个使用其"名称"作为主键.我知道这些将永远是独一无二的.在其中两个案例中(*_status表)我基本上使用ENUM的动态替换,因为状态选项将来可能会改变,而对于'网站'表,我知道网站的'名称'将始终独一无二.

我想知道这是否是合理的逻辑,当我知道名称总是一个唯一的标识符或灾难的食谱时,摆脱表ID?我不是一个经验丰富的DBA所以任何反馈,批评等都会非常有帮助.

感谢您抽时间阅读!

Mac*_*ros 16

有两个原因我总是在查找/ ENUM表中添加ID号:

  1. 如果您使用名称引用单个列表,则可以通过使用约束来更好地服务
  2. 如果要重命名其中一个client_status条目会发生什么?例如,如果您想将名称从"affiliate"更改为"affiliate user",则需要更新不必要的客户端表.ID号用作参考,名称是描述.

在网站表中,如果您确信该名称将是唯一的,则可以将其用作主键.我个人仍然会分配一个数字ID,因为它减少了外键表中使用的空间,我发现它更容易管理.

编辑:如上所述,如果重命名网站名称,您将遇到问题.通过将其作为主键,即使不是不可能在以后更改它,也将非常困难.

  • 上面的第二个是不使用该名称作为主键的最佳理由. (3认同)

Qua*_*noi 13

制作天然产品时PRIMARY KEY,请确保其独特性在您的控制之下.

如果你绝对肯定你永远不会有唯一性违规,那么可以将这些值用作PRIMARY KEY's'.

由于website_status并且client_status似乎是由您自己生成和使用的,因此将它们用作a是可以接受的PRIMARY KEY,尽管使用长键可能会影响性能.

website名字似乎在外部世界的控制之下,这就是为什么我要把它变成一个普通的领域.如果他们想重命名他们website怎么办?

反例将是SSNZIP代码:产生它们的不是你,并且不能保证它们不会被复制.


Bra*_*adC 9

Kimberly Tripp 在创建聚簇索引和选择主键(相关问题,但并非总是完全相同)的问题上有一系列精彩的博客文章(GUID作为PRIMARY KEYs和/或聚类键聚集索引辩论继续) ).她的建议是聚集索引/主键应该是:

  1. 独特(否则无用)
  2. (密钥用于所有非聚集索引和外键关系)
  3. 静态(您不想更改所有相关记录)
  4. 始终增加(因此新记录总是添加到表的末尾,而不必插入中间)

使用"名称"作为键,虽然它似乎满足#1,但不满足其他三个中的任何一个.

即使对于您的"查询"表,如果您的老板决定将所有联盟会员改为合作伙伴 s,该怎么办?您必须修改数据库中使用此值的所有行.

从性能的角度来看,我可能最关心的是一个关键是狭窄的.如果您的网站名称实际上是一个很长的URL,那么这可能会使任何非聚集索引的大小以及将其用作外键的所有表格都很大.