doudizhi947129 2017-10-22 11:00
浏览 32
已采纳

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

I've got two 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

that I want to normalize.

In ch_nav_items_test I store any navigation link the website has. menu_id is to distinct between frontend, backend, footer ... navigation. Parent is to build multilevel navigation. A house link would be on a second level.

When I create a new house, it'll have a display name (e.g. House Magic) and an automatically created alias (e.g. house-magic). This alias would be the link, too, with a prefix of "houses/" (e.g. houses/house-magic would be the link in ch_nav_items_test). The display name is stored in both tables atm but imho I can't use a foreign key, because the nav items table not only has house links, so there would be values that do not exist in the houses table. I am not able to build this foreign key.

What I end with is:

  • 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"

The ch_houses_test.alias-link I created temporarily to try to link to the nav link column with a foreign key without success.

It would be great to have a foreign link, because when I delete a house, I need to delete the related nav item link, too. Also, if I change the name of the house, the link in nav items needs to be changed, too. And so the alias does.

Atm I'm stuck at how to normalize this and I don't know what is best practice here. I'm okay with completely redefine my table structure but I want to keep it very simple.

I know that I can handle all this in php code, what I would normally do, because I'm more a php coder than a mysql expert, but if there is a simple way to handle most of this with few queries, I'd prefer this.

  • 写回答

1条回答 默认 最新

  • dony113407 2017-10-22 13:34
    关注

    This problem can be described as an analogy in OOP. If you need several classes to have the same kind of property or behavior. What would you do? You create an interface to group these classes.

    Now back to your example, the nav_item is the common property of house and other tables. What you need is a parent table or an interface that nav_item table can refer to. Let's call this table links and define it like this

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

    Then the houses table and other tables can create their own links and refer to

    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
    

    Finally, the nav_item can also refer to links belong to house or other entities

    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
    

    When you want to delete or update both the house and nav_item link, simply delete or update their corresponding record in links table. And in case you want to extend nav_item to other entities just refer these entities to links table.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 R语言Rstudio突然无法启动
  • ¥15 关于#matlab#的问题:提取2个图像的变量作为另外一个图像像元的移动量,计算新的位置创建新的图像并提取第二个图像的变量到新的图像
  • ¥15 改算法,照着压缩包里边,参考其他代码封装的格式 写到main函数里
  • ¥15 用windows做服务的同志有吗
  • ¥60 求一个简单的网页(标签-安全|关键词-上传)
  • ¥35 lstm时间序列共享单车预测,loss值优化,参数优化算法
  • ¥15 Python中的request,如何使用ssr节点,通过代理requests网页。本人在泰国,需要用大陆ip才能玩网页游戏,合法合规。
  • ¥100 为什么这个恒流源电路不能恒流?
  • ¥15 有偿求跨组件数据流路径图
  • ¥15 写一个方法checkPerson,入参实体类Person,出参布尔值