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

MySQL database normalization and best practice

我有两个 tables:

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我存储了网站有的任何导航link。 menu_id 用于区分前端、后端、页脚...导航。 Parent是建立多级导航。房子 link 会在第二层。

当我创建一个新房子时,它会有一个显示名称(例如 House Magic)和一个自动创建的别名(例如 house-magic)。此别名也将是 link,前缀为 "houses/"(例如 houses/house-magic 将是 ch_nav_items_test 中的 link)。显示名称存储在两个 tables atm 但恕我直言,我不能使用外键,因为导航项 table 不仅有房子 links,所以会有值房屋中不存在 table。我无法构建此外键。

我的结尾是:

我临时创建的ch_houses_test.alias-link试图link到导航link列用外键没有成功。

要是有外国的就好了link,因为我在删除房子的时候,也需要删除相关的导航项link。 另外,如果我更改房子的名称,导航项中的 link 也需要更改。别名也是如此。

Atm 我不知道如何对此进行规范化,我不知道这里的最佳做法是什么。 我可以完全重新定义我的 table 结构,但我想保持它非常简单。

我知道我可以用 php 代码处理所有这些,这是我通常会做的,因为我更像是 php 编码员而不是 mysql 专家,但是如果有一种简单的方法可以通过很少的查询来处理大部分问题,我更喜欢这种方法。

这个问题可以用OOP类比来形容。如果您需要多个 类 具有相同类型的 属性 或行为。你会怎么做?您创建一个界面来对这些 类.

进行分组

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

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

然后 houses table 和其他 table 可以创建自己的 link 并引用

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 或其他实体的 link

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

当您要删除或更新房子和nav_item link时,只需删除或更新它们在links table中的相应记录即可。如果您想将 nav_item 扩展到其他实体,只需将这些实体引用到 links table.