Can't create table 'e-learningsystem.chapter' (errno: 121) [duplicate] - mysql
I have troubles with forward engineering my MySQL database into WAMP server..
I was going to post an image of the schema but as this is my first post I can't.
Below is the executed script..
use aquaticstar;
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';
-- -----------------------------------------------------
-- Table `Students`
-- -----------------------------------------------------
DROP TABLE IF EXISTS `Students` ;
CREATE TABLE IF NOT EXISTS `Students` (
`id` VARCHAR(10) NOT NULL ,
`studentName` VARCHAR(45) NOT NULL ,
`gender` CHAR NOT NULL ,
`birthDate` DATETIME NOT NULL ,
`mNo` VARCHAR(10) NOT NULL ,
`contactName` VARCHAR(45) NOT NULL ,
`contactEmail` VARCHAR(45) NOT NULL ,
`contactPhone` INT(10) NOT NULL ,
`startDate` DATETIME NOT NULL ,
`remarks` VARCHAR(200) NULL ,
PRIMARY KEY (`id`) )
ENGINE = InnoDB;
-- -----------------------------------------------------
-- Table `Waiting List`
-- -----------------------------------------------------
DROP TABLE IF EXISTS `Waiting List` ;
CREATE TABLE IF NOT EXISTS `Waiting List` (
`wait_id` VARCHAR(5) NOT NULL ,
`name` VARCHAR(45) NULL ,
`contactName` VARCHAR(45) NULL ,
`contactPhone` INT(10) NULL ,
`contactEmail` VARCHAR(45) NULL ,
`status` CHAR NULL ,
`remarks` VARCHAR(200) NULL ,
PRIMARY KEY (`wait_id`) )
ENGINE = InnoDB;
-- -----------------------------------------------------
-- Table `Schedule`
-- -----------------------------------------------------
DROP TABLE IF EXISTS `Schedule` ;
CREATE TABLE IF NOT EXISTS `Schedule` (
`lesson_id` VARCHAR(10) NOT NULL ,
`day` VARCHAR(3) NOT NULL ,
`branch` VARCHAR(30) NOT NULL ,
`level` VARCHAR(30) NOT NULL ,
`time` TIME NOT NULL ,
`ae` VARCHAR(45) NOT NULL ,
PRIMARY KEY (`lesson_id`) )
ENGINE = InnoDB;
-- -----------------------------------------------------
-- Table `Link`
-- -----------------------------------------------------
DROP TABLE IF EXISTS `Link` ;
CREATE TABLE IF NOT EXISTS `Link` (
`link_id` VARCHAR(10) NOT NULL ,
`id` VARCHAR(10) NOT NULL ,
`lesson_id` VARCHAR(10) NOT NULL ,
PRIMARY KEY (`link_id`) ,
INDEX `id_idx` (`id` ASC) ,
INDEX `lesson_id_idx` (`lesson_id` ASC) ,
CONSTRAINT `id`
FOREIGN KEY (`id` )
REFERENCES `Students` (`id` )
ON DELETE NO ACTION
ON UPDATE NO ACTION,
CONSTRAINT `lesson_id`
FOREIGN KEY (`lesson_id` )
REFERENCES `Schedule` (`lesson_id` )
ON DELETE NO ACTION
ON UPDATE NO ACTION)
ENGINE = InnoDB;
-- -----------------------------------------------------
-- Table `Attendance`
-- -----------------------------------------------------
DROP TABLE IF EXISTS `Attendance` ;
CREATE TABLE IF NOT EXISTS `Attendance` (
`date` DATETIME NOT NULL ,
`attendance` VARCHAR(5) NOT NULL ,
`link_id` VARCHAR(10) NOT NULL ,
INDEX `link_id_idx` (`link_id` ASC) ,
CONSTRAINT `link_id`
FOREIGN KEY (`link_id` )
REFERENCES `Link` (`link_id` )
ON DELETE NO ACTION
ON UPDATE NO ACTION)
ENGINE = InnoDB;
SET SQL_MODE=#OLD_SQL_MODE;
SET FOREIGN_KEY_CHECKS=#OLD_FOREIGN_KEY_CHECKS;
SET UNIQUE_CHECKS=#OLD_UNIQUE_CHECKS;
-- -----------------------------------------------------
-- Data for table `Students`
-- -----------------------------------------------------
START TRANSACTION;
INSERT INTO `Students` (`id`, `studentName`, `gender`, `birthDate`, `mNo`, `contactName`, `contactEmail`, `contactPhone`, `startDate`, `remarks`) VALUES ('s001', 'Sam Khew', 'm', '12/12/1991', 'nm', 'May Khew', 'may#gmail.com', 0198829387, '12/07/2011', NULL);
INSERT INTO `Students` (`id`, `studentName`, `gender`, `birthDate`, `mNo`, `contactName`, `contactEmail`, `contactPhone`, `startDate`, `remarks`) VALUES ('s002', 'Joe Biden', 'm', '13/03/2003', 'nm', 'Layla Biden', 'layla#gmail.com', 0199283763, '14/05/2011', NULL);
INSERT INTO `Students` (`id`, `studentName`, `gender`, `birthDate`, `mNo`, `contactName`, `contactEmail`, `contactPhone`, `startDate`, `remarks`) VALUES ('s003', 'Bob Builder', 'm', '14/02/2002', 'LK920K', 'Mama Builder', 'mama#yahoo.com', 0167728376, '29/02/2012', NULL);
INSERT INTO `Students` (`id`, `studentName`, `gender`, `birthDate`, `mNo`, `contactName`, `contactEmail`, `contactPhone`, `startDate`, `remarks`) VALUES ('s004', 'Kenny Koh', 'm', '18/02/1999', 'MM992', 'Lisa Koh', 'lk#hotmail.com', 0123160231, '19/01/2012', NULL);
INSERT INTO `Students` (`id`, `studentName`, `gender`, `birthDate`, `mNo`, `contactName`, `contactEmail`, `contactPhone`, `startDate`, `remarks`) VALUES ('s005', 'Jane Doe', 'f', '29/09/1999', 'nm', 'Jackie Doe', 'jackied#gmail.com', 0127736254, '02/03/2012', NULL);
INSERT INTO `Students` (`id`, `studentName`, `gender`, `birthDate`, `mNo`, `contactName`, `contactEmail`, `contactPhone`, `startDate`, `remarks`) VALUES ('s006', 'Lola Lai', 'f', '02/05/2004', 'nm', 'Mark Lai', 'mark#gmail.com', 0198827365, '11/09/2011', NULL);
COMMIT;
-- -----------------------------------------------------
-- Data for table `Schedule`
-- -----------------------------------------------------
START TRANSACTION;
INSERT INTO `Schedule` (`lesson_id`, `day`, `branch`, `level`, `time`, `ae`) VALUES ('sat1_s4', 'Sat', 'Sunway', 'basic', '4pm', 'Aini');
INSERT INTO `Schedule` (`lesson_id`, `day`, `branch`, `level`, `time`, `ae`) VALUES ('sat1_s5', 'Sat', 'Sunway', 'basic', '5pm', 'Aini');
INSERT INTO `Schedule` (`lesson_id`, `day`, `branch`, `level`, `time`, `ae`) VALUES ('sat1_s6', 'Sat', 'Sunway', 'basic', '6pm', 'Aini');
INSERT INTO `Schedule` (`lesson_id`, `day`, `branch`, `level`, `time`, `ae`) VALUES ('sat2_s4', 'Sat', 'Sunway', 'advance', '4pm', 'Nina');
INSERT INTO `Schedule` (`lesson_id`, `day`, `branch`, `level`, `time`, `ae`) VALUES ('sat2_s5', 'Sat', 'Sunway', 'advance', '5pm', 'Nina');
INSERT INTO `Schedule` (`lesson_id`, `day`, `branch`, `level`, `time`, `ae`) VALUES ('sat3_s6', 'Sat', 'Sunway', 'pre-comp', '6pm', 'Marcus');
COMMIT;
-- -----------------------------------------------------
-- Data for table `Link`
-- -----------------------------------------------------
START TRANSACTION;
INSERT INTO `Link` (`link_id`, `id`, `lesson_id`) VALUES ('L001', 's001', 'sat1_s4');
INSERT INTO `Link` (`link_id`, `id`, `lesson_id`) VALUES ('L002', 's002', 'sat1_s5');
INSERT INTO `Link` (`link_id`, `id`, `lesson_id`) VALUES ('L003', 's003', 'sat1_s6');
INSERT INTO `Link` (`link_id`, `id`, `lesson_id`) VALUES ('L004', 's004', 'sat2_s4');
INSERT INTO `Link` (`link_id`, `id`, `lesson_id`) VALUES ('L005', 's005', 'sat1_s5');
COMMIT;
-- -----------------------------------------------------
-- Data for table `Attendance`
-- -----------------------------------------------------
START TRANSACTION;
INSERT INTO `Attendance` (`date`, `attendance`, `link_id`) VALUES ('26/9/2012', '1', NULL);
COMMIT;
But then I get this error:
Executing SQL script in server
ERROR: Error 1005: Can't create table 'aquaticstar.link' (errno: 121)
I can't figure out why. Can anyone help me?
I searched quickly for you, and it brought me here. I quote:
You will get this message if you're trying to add a constraint with a
name that's already used somewhere else
To check constraints use the following SQL query:
SELECT
constraint_name,
table_name
FROM
information_schema.table_constraints
WHERE
constraint_type = 'FOREIGN KEY'
AND table_schema = DATABASE()
ORDER BY
constraint_name;
Look for more information there, or try to see where the error occurs. Looks like a problem with a foreign key to me.
Foreign Key Constraint Names Have to be Unique Within a Database
Both #Dorvalla’s answer and this blog post mentioned above pointed me into the right direction to fix the problem for myself; quoting from the latter:
If the table you're trying to create includes a foreign key constraint, and you've provided your own name for that constraint, remember that it must be unique within the database.
I wasn’t aware of that. I have changed my foreign key constraint names according to the following schema which appears to be used by Ruby on Rails applications, too:
<TABLE_NAME>_<FOREIGN_KEY_COLUMN_NAME>_fk
For the OP’s table this would be Link_lession_id_fk, for example.
You can login to mysql and type
mysql> SHOW INNODB STATUS\G
You will have all the output and you should have a better idea of what the error is.
I faced this error (errno 121) but it was caused by mysql-created intermediate tables that had been orphaned, preventing me from altering a table even though no such constraint name existed across any of my tables. At some point, my MySQL had crashed or failed to cleanup an intermediate table (table name starting with a #sql-) which ended up presenting me with an error such as: Can't create table '#sql-' (errno 121) when trying to run an ALTER TABLE with certain constraint names.
According to the docs at http://dev.mysql.com/doc/refman/5.7/en/innodb-troubleshooting-datadict.html , you can search for these orphan tables with:
SELECT * FROM INFORMATION_SCHEMA.INNODB_SYS_TABLES WHERE NAME LIKE '%#sql%';
The version I was working with was 5.1, but the above command only works on versions >= 5.6 (manual is incorrect about it working for 5.5 or earlier, because INNODB_SYS_TABLES does not exist in such versions). I was able to find the orphaned temporary table (which did not match the one named in the message) by searching my mysql data directory in command line:
find . -iname '#*'
After discovering the filename, such as #sql-9ad_15.frm, I was able to drop that orphaned table in MySQL:
USE myschema;
DROP TABLE `#mysql50##sql-9ad_15`;
After doing so, I was then able to successfully run my ALTER TABLE.
For completeness, as per the MySQL documentation linked, "the #mysql50# prefix tells MySQL to ignore file name safe encoding introduced in MySQL 5.1."
If you have a foreign key definition in some table and the name of the foreign key is used elsewhere as another foreign key you will have this error.
If you want to fix quickly, Forward Engineer again and check "Generate DROP SCHEMA" option and proceed.
I assume the database doesn't contain data, so dropping it won't affect.
Something I noticed was that I had "other_database" and "Other_Database" in my databases.
That caused this problem as I actually had same reference in other database which caused this mysterious error!
mysql> SHOW ENGINE INNODB STATUS;
But in my case only this way could help:
1. Make backup of current DB
2. Drop DB (not all tables, but DB)
3. Create DB (check that you still have previleges)
4. Restore DB from backup
Related
Can I run a SELECT query that depends on two rows from a table without using subqueries
Suppose the schemas are users(id, name) users_attributes(user_id, attribute_name, attribute_value) Sample data: -- -- Database: `sample_db` -- CREATE DATABASE IF NOT EXISTS `sample_db` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci; USE `sample_db`; -- -------------------------------------------------------- -- -- Table structure for table `users` -- CREATE TABLE `users` ( `id` int(11) NOT NULL, `name` varchar(50) NOT NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; -- -- Dumping data for table `users` -- INSERT INTO `users` (`id`, `name`) VALUES (1, 'Tim'), (2, 'Joe'), (3, 'Bob'); -- -------------------------------------------------------- -- -- Table structure for table `users_attributes` -- CREATE TABLE `users_attributes` ( `user_id` int(11) NOT NULL, `attribute_name` varchar(50) NOT NULL, `attribute_value` varchar(50) NOT NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; -- -- Dumping data for table `users_attributes` -- INSERT INTO `users_attributes` (`user_id`, `attribute_name`, `attribute_value`) VALUES (1, 'height', '10'), (1, 'over_18', 'yes'), (2, 'height', '5'), (3, 'height', '7'); -- -- Indexes for dumped tables -- -- -- Indexes for table `users` -- ALTER TABLE `users` ADD PRIMARY KEY (`id`); -- -- Indexes for table `users_attributes` -- ALTER TABLE `users_attributes` ADD UNIQUE KEY `user_id` (`user_id`,`attribute_name`,`attribute_value`); -- -- AUTO_INCREMENT for dumped tables -- -- -- AUTO_INCREMENT for table `users` -- ALTER TABLE `users` MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=4; COMMIT; Right now I'm calling INNER JOIN on a specific attribute_name so my selection also returns that along with the user id and name. Now I want to exclude from whatever I selected, if they contain a certain other attribute. I know I can accomplish that by using a NOT IN (SELECT ...) conditional but can I do that without having to select again? EDIT: Attributes may or may not exist for all users. For example, I would like to fetch id, name, attribute_value where attribute_name = height but only if attribute_name over_18 does not exist or is 'no'
SQL insert query so slow
Each 10,000 rows take about 124 second to insert ,how this can be faster This is the table i insert to CREATE TABLE `orders` (`oid` int(11) NOT NULL AUTO_INCREMENT, `countryCode` varchar(10) NOT NULL, `date` datetime NOT NULL, `id` bigint(20) NOT NULL, `productId` bigint(20) NOT NULL, PRIMARY KEY (`oid`), UNIQUE KEY `id` (`id`), KEY `date` (`date`), KEY `productId` (`productId`) ) ENGINE=InnoDB AUTO_INCREMENT=4833010 DEFAULT CHARSET=latin1 this is the query i used ALTER TABLE `orders` DISABLE KEYS; SET FOREIGN_KEY_CHECKS=0; INSERT IGNORE INTO `orders` (`countryCode`, `date`, `id`,`productId`) VALUES ('ru','2019-04-09 06:59',100453324298986,32829863707) , ('fr','2019-04-09 05:59',100645420835625,32829863707) , ('ru','2019-04-08 12:04',704482263524094,32829863707) .......etc 10,000 rows here at once
Try to write insert statement as START TRANSACTION; INSERT INTO `insert_table` (`datetime`, `uid`, `content`, `type`) VALUES ('0', 'userid_0', 'content_0', 0); INSERT INTO `insert_table` (`datetime`, `uid`, `content`, `type`) VALUES ('1', 'userid_1', 'content_1', 1); ... COMMIT;
I think it's slow because you trying to INSERT bulk records at once. You have several methods to speedup the process. 1) Insert records batch wise. ( 500-1000 records at a time ) 2) Increase Memory parameters in MYSQL. so the memory will be increased. (http://www.geeksengine.com/database/data-manipulation/bulk-insert.php) Try This for batch Update SET autocommit=0; SET unique_checks=0; SET foreign_key_checks=0; SET GLOBAL bulk_insert_buffer_size =1024*1024*512; START TRANSACTION; INSERT IGNORE INTO `orders` (`countryCode`, `date`, `id`,`productId`) VALUES ('ru','2019-04-09 06:59',100453324298986,32829863707) , ('fr','2019-04-09 05:59',100645420835625,32829863707) , ('ru','2019-04-08 12:04',704482263524094,32829863707) .......etc 600 rows here at once COMMIT; START TRANSACTION; INSERT IGNORE INTO `orders` (`countryCode`, `date`, `id`,`productId`) VALUES ('ru','2019-04-09 06:59',100453324298986,32829863707) , ('fr','2019-04-09 05:59',100645420835625,32829863707) , ('ru','2019-04-08 12:04',704482263524094,32829863707) .......etc 600 rows here at once COMMIT; Note: 1) If this is slow Try changing bulk_insert_buffer_size and no of rows per insert. 2) Check your PC Free Memory/CPU before executing the query . try to free it as much as possible
Retrieving all 'Child' items using MySQL query
I am attempting to write a SQL query to generate a table containing all 'child' items for each 'parent' (in this case Element). I have created a simplified instance of this problem below and setup a db-fiddle instance for sake of clarity. Given the following dummy data: -- ----------------------------------------------------- -- Table `Element` -- ----------------------------------------------------- CREATE TABLE IF NOT EXISTS `Element` ( `idElement` INT NOT NULL AUTO_INCREMENT, `Element_Name` VARCHAR(45) NULL, PRIMARY KEY (`idElement`)) ENGINE = InnoDB; -- ----------------------------------------------------- -- Table `Property` -- ----------------------------------------------------- CREATE TABLE IF NOT EXISTS `Property` ( `idProperty` INT NOT NULL AUTO_INCREMENT, `Property_Text` VARCHAR(45) NULL, `Property_Node_ID` INT NULL, `Element_idElement` INT NOT NULL, PRIMARY KEY (`idProperty`), INDEX `fk_Property_Element1_idx` (`Element_idElement` ASC), CONSTRAINT `fk_Property_Element1` FOREIGN KEY (`Element_idElement`) REFERENCES `Element` (`idElement`) ) ENGINE = InnoDB; -- ----------------------------------------------------- -- Table `Property_2` -- ----------------------------------------------------- CREATE TABLE IF NOT EXISTS `Property_2` ( `idProperty_2` INT NOT NULL AUTO_INCREMENT, `Property_2_Text` VARCHAR(45) NULL, `Property_Node_ID` INT NULL, `Element_idElement` INT NOT NULL, PRIMARY KEY (`idProperty_2`), INDEX `fk_Property_2_Element_idx` (`Element_idElement` ASC), CONSTRAINT `fk_Property_2_Element` FOREIGN KEY (`Element_idElement`) REFERENCES `Element` (`idElement`) ) ENGINE = InnoDB; INSERT INTO `Element` (`idElement`, `Element_Name`) VALUES (NULL, 'element_1'); INSERT INTO `Element` (`idElement`, `Element_Name`) VALUES (NULL, 'element_2'); INSERT INTO `Property` (`idProperty`, `Property_Text`, `Property_Node_ID`, `Element_idElement`) VALUES (NULL, 'property_a', NULL, '1'); INSERT INTO `Property` (`idProperty`, `Property_Text`, `Property_Node_ID`, `Element_idElement`) VALUES (NULL, 'property_b', NULL, '1'); INSERT INTO `Property` (`idProperty`, `Property_Text`, `Property_Node_ID`, `Element_idElement`) VALUES (NULL, 'property_c', NULL, '2'); INSERT INTO `Property_2` (`idProperty_2`, `Property_2_Text`, `Property_Node_ID`, `Element_idElement`) VALUES (NULL, 'property_2_a', NULL, '1'); INSERT INTO `Property_2` (`idProperty_2`, `Property_2_Text`, `Property_Node_ID`, `Element_idElement`) VALUES (NULL, 'property_2_b', NULL, '2'); INSERT INTO `Property_2` (`idProperty_2`, `Property_2_Text`, `Property_Node_ID`, `Element_idElement`) VALUES (NULL, 'property_2_c', NULL, '2'); I would like to output the following where each unique combination of the element and its properties are displayed row-by-row. They are ordered first by the element, then by the first property, and finally by the last property: ------------------------------------- element | property | property_2 ------------------------------------- element_1 | property_a | property_2_a element_1 | property_b | property_2_a element_2 | property_c | property_2_b element_2 | property_c | property_2_c Please see the link to the db-fiddle: https://www.db-fiddle.com/f/csqTVJFTtpodqPksQtyrbs/0. Any help would be greatly appreciated 😄
I don't really understand the problem - and the naming policy is confusing - but what part of it does the following fail to address? SELECT e.Element_Name element , p.Property_text property , p2.Property_2_text property_2 FROM Element e JOIN Property p ON p.Element_idElement = e.idElement JOIN Property_2 p2 ON p2.Element_idElement = e.idElement ORDER BY element , property , property_2;
how to get average time 'xx:xx:xx' on mysql?
please see the the test data bellow. I want to get the avgtime (=timeonsite/visits) and display as "xx:xx:xx" result in mysql. how can I get it? SET FOREIGN_KEY_CHECKS=0; -- ---------------------------- -- Table structure for `t` -- ---------------------------- DROP TABLE IF EXISTS `t`; CREATE TABLE `t` ( `id` int(11) NOT NULL auto_increment, `timeOnsite` time default NULL, `visits` int(11) default NULL, PRIMARY KEY (`id`) ) ENGINE=MyISAM AUTO_INCREMENT=4 DEFAULT CHARSET=utf8; -- ---------------------------- -- Records of t -- ---------------------------- INSERT INTO `t` VALUES ('1', '04:05:30', '20'); INSERT INTO `t` VALUES ('2', '03:00:00', '10'); INSERT INTO `t` VALUES ('3', '00:01:30', '17');
You can use TIME_TO_SEC function to change xx:xx:xx format to seconds. SELECT TIME_TO_SEC('00:01:30') / 17; # return 5.2941 And then through SEC_TO_TIME you can convert seconds to time back as below : SELECT SEC_TO_TIME(TIME_TO_SEC('00:01:30') / 17); # return 00:00:05
Are sure that you calculate avgtime in such way? If yes, mysql select below: select id, timeOnsite,visits, SEC_TO_TIME(TIME_TO_SEC(timeOnsite)/visits) as avgtime from t
groups and sub-group up to 5 level database structure
i was wondering what is the best structure for a table in mysql, The structure needs to have: Parent (level 0) -region (inside regions are)(level 1) -countrys (inside countrys are)(level 2) -Districts (level 3) So I need to store all that info but in the same table, any clues?? If you need to know i building this app on cakephp. Thanks in advance.
I've impulsively made an EER diagram for your situation. Please tell me if it works (and if you agree), I'll be awaiting your feedback. 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; [(Mostly) auto-generated code from MySQL Workbench 5.2] Note that the trigger insert_location determines item's level at registration time, increasing so the parent's level by one unit.