MySQL数据库规范化和最佳实践

时间:2017-10-22 11:00:09

标签: php mysql database normalization

我有两张桌子:

CREATE TABLE `ch_nav_items_test` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `menu_id` int(11) DEFAULT NULL,
  `parent` int(4) DEFAULT NULL,
  `displayname` varchar(60) CHARACTER SET latin1 DEFAULT NULL,
  `link` varchar(60) CHARACTER SET latin1 DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `link` (`link`)
) ENGINE=InnoDB AUTO_INCREMENT=40 DEFAULT CHARSET=utf8

CREATE TABLE `ch_houses_test` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `displayname` varchar(30) DEFAULT NULL,
  `alias` varchar(30) DEFAULT NULL,
  `street` varchar(100) DEFAULT '',
  `zip` int(5) DEFAULT NULL,
  `city` varchar(100) DEFAULT NULL,
  `active` tinyint(1) DEFAULT NULL,
  `alias_link` varchar(60) CHARACTER SET latin1 DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `alias_link` (`alias_link`)
) ENGINE=InnoDB AUTO_INCREMENT=19 DEFAULT CHARSET=utf8

我想要规范化。

在ch_nav_items_test中,我存储了网站的所有导航链接。 menu_id是区分前端,后端,页脚...导航。 父是建立多级导航。房屋链接将位于第二层。

当我创建一个新房子时,它将有一个显示名称(例如House Magic)和一个自动创建的别名(例如house-magic)。这个别名也是链接,前缀为“houses /”(例如,house / house-magic将是ch_nav_items_test中的链接)。显示名称存储在两个表atm中,但我不能使用外键,因为导航项表不仅具有内部链接,因此将存在于house表中不存在的值。我无法构建这个外键。

我最终得到的是:

  • ch_nav_items_test.displayname =“House Magic”
  • ch_nav_itmes_test.link =“houses / house-magic”
  • ch_houses_test.displayname =“House Magic”
  • ch_houses_test.alias =“house-magic”
  • ch_houses_test.alias-link =“houses / house-magic”

我临时创建的ch_houses_test.alias-link尝试使用外键链接到nav链接列但没有成功。

有一个外国链接会很棒,因为当我删除一个房子时,我也需要删除相关的导航项链接。 此外,如果我更改房屋的名称,也需要更改导航项中的链接。别名就是这样。

我仍然坚持如何规范这一点,我不知道这里的最佳做法是什么。 我没关系完全重新定义我的表结构,但我想保持它非常简单。

我知道我可以在PHP代码中处理所有这些,我通常会这样做,因为我更像是一个php编码器而不是mysql专家,但是如果有一个简单的方法来处理大部分这个问题,我更喜欢这个。

1 个答案:

答案 0 :(得分:1)

这个问题可以在OOP中类比。如果您需要多个类来拥有相同类型的属性或行为。你会怎么做?您可以创建一个界面来对这些类进行分组。

现在回到您的示例,nav_itemhouse和其他表的公共属性。您需要的是父表或nav_item表可以引用的接口。让我们调用此表links并像这样定义

CREATE TABLE `links` (
  `id` varchar(60) NOT NULL CHARACTER SET latin1,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8

然后houses表和其他表可以创建自己的链接并引用

CREATE TABLE `ch_houses_test` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  ...
  `link` varchar(60) NOT NULL CHARACTER SET latin1,
  PRIMARY KEY (`id`),
  CONSTRAINT FOREIGN KEY (`link`) REFERENCES `links` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=19 DEFAULT CHARSET=utf8

最后,nav_item还可以引用属于house或其他实体的链接

CREATE TABLE `ch_nav_items_test` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `menu_id` int(11) DEFAULT NULL,
  `parent` int(4) DEFAULT NULL,
  `displayname` varchar(60) CHARACTER SET latin1 DEFAULT NULL,
  `link` varchar(60) CHARACTER SET latin1 DEFAULT NULL,
  PRIMARY KEY (`id`),
  CONSTRAINT FOREIGN KEY (`link`) REFERENCES `links` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=40 DEFAULT CHARSET=utf8

如果要删除或更新house和nav_item链接,只需删除或更新links表中的相应记录即可。如果您想将nav_item扩展到其他实体,只需将这些实体引用到links表。