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_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试图link到导航link列用外键没有成功。
要是有外国的就好了link,因为我在删除房子的时候,也需要删除相关的导航项link。
另外,如果我更改房子的名称,导航项中的 link 也需要更改。别名也是如此。
Atm 我不知道如何对此进行规范化,我不知道这里的最佳做法是什么。
我可以完全重新定义我的 table 结构,但我想保持它非常简单。
我知道我可以用 php 代码处理所有这些,这是我通常会做的,因为我更像是 php 编码员而不是 mysql 专家,但是如果有一种简单的方法可以通过很少的查询来处理大部分问题,我更喜欢这种方法。
这个问题可以用OOP类比来形容。如果您需要多个 类 具有相同类型的 属性 或行为。你会怎么做?您创建一个界面来对这些 类.
进行分组
现在回到您的示例,nav_item
是 house
和其他 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.
我有两个 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_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试图link到导航link列用外键没有成功。
要是有外国的就好了link,因为我在删除房子的时候,也需要删除相关的导航项link。 另外,如果我更改房子的名称,导航项中的 link 也需要更改。别名也是如此。
Atm 我不知道如何对此进行规范化,我不知道这里的最佳做法是什么。 我可以完全重新定义我的 table 结构,但我想保持它非常简单。
我知道我可以用 php 代码处理所有这些,这是我通常会做的,因为我更像是 php 编码员而不是 mysql 专家,但是如果有一种简单的方法可以通过很少的查询来处理大部分问题,我更喜欢这种方法。
这个问题可以用OOP类比来形容。如果您需要多个 类 具有相同类型的 属性 或行为。你会怎么做?您创建一个界面来对这些 类.
进行分组现在回到您的示例,nav_item
是 house
和其他 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.