我想知道 mysql 中表的最佳结构是什么,该结构需要具有:
Parent (level 0)
-region (inside regions are)(level 1)
-countrys (inside countrys are)(level 2)
-Districts (level 3)
所以我需要将所有这些信息存储在同一张表中,有什么线索吗?如果你需要知道我在 cakephp 上构建这个应用程序。
提前致谢。
我想知道 mysql 中表的最佳结构是什么,该结构需要具有:
Parent (level 0)
-region (inside regions are)(level 1)
-countrys (inside countrys are)(level 2)
-Districts (level 3)
所以我需要将所有这些信息存储在同一张表中,有什么线索吗?如果你需要知道我在 cakephp 上构建这个应用程序。
提前致谢。
我冲动地为您的情况制作了一个 EER 图。
请告诉我它是否有效(如果您同意),我将等待您的反馈。
SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0;
SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0;
SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='TRADITIONAL,ALLOW_INVALID_DATES';
DROP SCHEMA IF EXISTS `hierarchy` ;
CREATE SCHEMA IF NOT EXISTS `hierarchy` DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci ;
USE `hierarchy` ;
-- -----------------------------------------------------
-- Table `hierarchy`.`level`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `hierarchy`.`level` (
`id` TINYINT UNSIGNED NOT NULL AUTO_INCREMENT ,
`name` VARCHAR(20) NOT NULL ,
PRIMARY KEY (`id`) ,
UNIQUE INDEX `name_UNIQUE` (`name` ASC) )
ENGINE = InnoDB;
-- -----------------------------------------------------
-- Table `hierarchy`.`location`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `hierarchy`.`location` (
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT ,
`parent` INT UNSIGNED NULL ,
`name` VARCHAR(50) NOT NULL ,
`level` TINYINT UNSIGNED NULL ,
PRIMARY KEY (`id`) ,
INDEX `fk_location_location_idx` (`parent` ASC) ,
INDEX `fk_location_level1_idx` (`level` ASC) ,
INDEX `index_name` (`name` ASC) ,
CONSTRAINT `fk_location_location`
FOREIGN KEY (`parent` )
REFERENCES `hierarchy`.`location` (`id` )
ON DELETE NO ACTION
ON UPDATE NO ACTION,
CONSTRAINT `fk_location_level1`
FOREIGN KEY (`level` )
REFERENCES `hierarchy`.`level` (`id` )
ON DELETE NO ACTION
ON UPDATE NO ACTION)
ENGINE = InnoDB;
USE `hierarchy` ;
-- -----------------------------------------------------
-- Placeholder table for view `hierarchy`.`details_location`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `hierarchy`.`details_location` (`location_id` INT, `location_name` INT, `parent_id` INT, `level_id` INT, `level_name` INT, `children` INT);
-- -----------------------------------------------------
-- View `hierarchy`.`details_location`
-- -----------------------------------------------------
DROP TABLE IF EXISTS `hierarchy`.`details_location`;
USE `hierarchy`;
CREATE OR REPLACE VIEW `hierarchy`.`details_location` AS
SELECT
x.`id` AS `location_id`,
x.`name` AS `location_name`,
IFNULL(x.`parent`, 0) AS `parent_id`,
y.`id` AS `level_id`,
y.`name` AS `level_name`,
(SELECT COUNT(*) FROM location AS l WHERE l.parent = x.id) AS `children`
FROM location AS `x`
INNER JOIN `level` AS `y`
ON (x.`level` = y.id);
USE `hierarchy`;
DELIMITER $$
USE `hierarchy`$$
CREATE TRIGGER `insert_location` BEFORE INSERT ON location
FOR EACH ROW BEGIN
DECLARE x INT UNSIGNED DEFAULT 1;
IF NEW.parent IS NOT NULL THEN
SELECT `level`+1 INTO x FROM location WHERE id = NEW.parent;
END IF;
SET NEW.`level` = x;
END$$
DELIMITER ;
SET SQL_MODE=@OLD_SQL_MODE;
SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS;
SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS;
-- -----------------------------------------------------
-- Data for table `hierarchy`.`level`
-- -----------------------------------------------------
START TRANSACTION;
USE `hierarchy`;
INSERT INTO `hierarchy`.`level` (`id`, `name`) VALUES (1, 'parent');
INSERT INTO `hierarchy`.`level` (`id`, `name`) VALUES (2, 'region');
INSERT INTO `hierarchy`.`level` (`id`, `name`) VALUES (3, 'country');
INSERT INTO `hierarchy`.`level` (`id`, `name`) VALUES (4, 'district');
COMMIT;
INSERT INTO location (parent,name,level) VALUES
(NULL,'a1',NULL), (NULL,'a2',NULL), (NULL,'a3',NULL);
INSERT INTO location (parent,name,level) VALUES
(1,'b1',NULL), (1,'b2',NULL), (2,'b3',NULL),
(2,'b4',NULL), (3,'b5',NULL), (3,'b6',NULL);
INSERT INTO location (parent,name,level) VALUES
(4,'c1',NULL), (4,'c2',NULL), (5,'c3',NULL),
(5,'c4',NULL), (6,'c5',NULL), (6,'c6',NULL),
(7,'c7',NULL), (7,'c8',NULL), (8,'c9',NULL),
(8,'c10',NULL), (9,'c11',NULL), (9,'c12',NULL);
SELECT * FROM details_location;
[(大部分)来自 MySQL Workbench 5.2 的自动生成代码]
请注意,触发器insert_location
在注册时确定项目的级别,因此父级的级别增加一个单位。