MySQL Hierarchical Data Reference - Closing Table Method

I am trying to implement a system in MySQL to store hierarchical data. I decided to go with the embedded system here , as described by Bill Karwin starting with slide number 40. I am trying to set up a database, so the EntryPaths table is EntryPaths maintained.

Update: I updated the SQL database a bit. I think I have things that work to upgrade. After starting the database, create SQL, try the following

First look at how this post looks.

 -- Example query to return a full library entry (0x02 is the entry iD) SELECT `Library`.* FROM `Library` LEFT JOIN `EntryPaths` ON `Library`.`iD` = `EntryPaths`.`descendant` WHERE `EntryPaths`.`ancestor` = 0x02 ORDER BY `Library`.`subsectionOf`, `Library`.`subsectionOrder` 

And what does this look like

 -- Example query to return a full library entry (0x08 is the entry iD) SELECT `Library`.* FROM `Library` LEFT JOIN `EntryPaths` ON `Library`.`iD` = `EntryPaths`.`descendant` WHERE `EntryPaths`.`ancestor` = 0x08 ORDER BY `Library`.`subsectionOf`, `Library`.`subsectionOrder` 

There are several children in the first record viewed, the second has no children. Run the following update to return the College Years node (and its children) to John Doe

 UPDATE `Library` SET `subsectionOf` = 0x08 WHERE `Library`.`iD` = 0x04; 

If you re-run the two statements above, you will see that the items were removed from Jane Doe , but they were not added to John Doe as expected. The Library_Update trigger Library_Update to blame, but I'm running out of ideas to fix it.

The database creates SQL with data samples:

 -- MYSQL SET FOREIGN_KEY_CHECKS=0; DROP TRIGGER IF EXISTS Library_Insert; DROP TRIGGER IF EXISTS Library_Update; DROP TABLE IF EXISTS Users; DROP TABLE IF EXISTS Attributes; DROP TABLE IF EXISTS LibraryHistory; DROP TABLE IF EXISTS EntryPaths; DROP TABLE IF EXISTS Library; SET FOREIGN_KEY_CHECKS=1; CREATE TABLE `Users` ( `iD` VARBINARY(16) NOT NULL, -- UUID & PK `libraryID` VARBINARY(16), -- Library UUID & FK (The library entry for this person) `email` NVARCHAR(255) NOT NULL, -- Email address `nickname` NVARCHAR(255) NOT NULL, -- Nickname used for display `firstname` NVARCHAR(255), -- Real first name `lastname` NVARCHAR(255), -- Real last name `joinDate` DATETIME NOT NULL, -- Date the account was created PRIMARY KEY (`iD`) ) ENGINE = MYISAM; CREATE TABLE `Library` ( `iD` VARBINARY(16) NOT NULL, -- UUID & PK `name` NVARCHAR(500) NOT NULL, -- Name for the entry `contentType` NVARCHAR(50) NOT NULL, -- Mime type of data `content` LONGBLOB NOT NULL, -- Data a for the entry `subsectionOf` VARBINARY(16), -- Library UUID & FK `subsectionOrder` INT, -- Oder of Subsections `lastModifiedBy` VARBINARY(16), -- User UUID & FK `lastModified` DATETIME NOT NULL, -- Last time the record was updated PRIMARY KEY (`iD`), FOREIGN KEY (`subsectionOf`) REFERENCES Library(`iD`) ON DELETE CASCADE, FOREIGN KEY (`lastModifiedBy`) REFERENCES Users(`iD`), INDEX(`name`) ) ENGINE = MYISAM; -- Trigger to update the EntryPaths table for new entries DELIMITER // CREATE TRIGGER `Library_Insert` AFTER INSERT ON `Library` FOR EACH ROW BEGIN INSERT INTO `EntryPaths` (`ancestor`, `descendant`, `len`) SELECT `ancestor`, NEW.`iD`, len + 1 FROM `EntryPaths` WHERE `descendant` = NEW.`subsectionOf` UNION ALL SELECT NEW.`iD`, NEW.`iD`, 0; END; // DELIMITER ; DELIMITER // CREATE TRIGGER `Library_Update` BEFORE UPDATE ON `Library` FOR EACH ROW BEGIN -- Add the old entry into the history table INSERT INTO `LibraryHistory` VALUES(UNHEX(REPLACE(UUID(),'-','')), OLD.`iD`, OLD.`name`, OLD.`contentType`, OLD.`content`, OLD.`subsectionOf`, OLD.`subsectionOrder`, OLD.`lastModifiedBy`, OLD.`lastModified`); -- From http://www.mysqlperformanceblog.com/2011/02/14/moving-subtrees-in-closure-table/ IF OLD.`subsectionOf` != NEW.`subsectionOf` THEN -- Remove the node from its current parent DELETE a FROM `EntryPaths` AS a JOIN `EntryPaths` AS d ON a.`descendant` = d.`descendant` LEFT JOIN `EntryPaths` AS x ON x.`ancestor` = d.`ancestor` AND x.`descendant` = a.`ancestor` WHERE d.`ancestor` = OLD.`iD` AND x.`ancestor` IS NULL; -- Add the node to its new parent -- FIXME: Not Working yet INSERT `EntryPaths` (`ancestor`, `descendant`, `len`) SELECT supertree.`ancestor`, subtree.`descendant`, supertree.`len`+subtree.`len`+1 FROM `EntryPaths` AS supertree JOIN `EntryPaths` AS subtree WHERE subtree.`ancestor` = NEW.`iD` AND supertree.`descendant` = NEW.`subsectionOf`; END IF; END; // DELIMITER ; CREATE TABLE `EntryPaths` ( `ancestor` VARBINARY(16) NOT NULL, `descendant` VARBINARY(16) NOT NULL, `len` VARBINARY(16) NOT NULL, PRIMARY KEY (`ancestor`, `descendant`), FOREIGN KEY (`ancestor`) REFERENCES Library(`iD`) ON DELETE CASCADE, FOREIGN KEY (`descendant`) REFERENCES Library(`iD`) ON DELETE CASCADE ) ENGINE = MYISAM; CREATE TABLE `LibraryHistory` ( `iD` VARBINARY(16) NOT NULL, -- UUID & PK `libraryID` VARBINARY(16) NOT NULL, -- Library UUID & FK `name` NVARCHAR(500) NOT NULL, -- Name for the entry `contentType` NVARCHAR(50) NOT NULL, -- Mime type of data `content` LONGBLOB NOT NULL, -- Data a for the entry `subsectionOf` VARBINARY(16), -- Library UUID & FK `subsectionOrder` INT, -- Oder of Subsections `lastModifiedBy` VARBINARY(16), -- User UUID & FK `lastModified` DATETIME NOT NULL, -- Last time the record was updated PRIMARY KEY (`iD`), FOREIGN KEY (`libraryID`) REFERENCES Library(`iD`) ON DELETE CASCADE, FOREIGN KEY (`lastModifiedBy`) REFERENCES Users(`iD`) ) ENGINE = MYISAM; CREATE TABLE `Attributes` ( `iD` VARBINARY(16) NOT NULL, -- UUID & PK (Potentially could be removed) `libraryID` VARBINARY(16) NOT NULL, -- Library UUID & FK `name` NVARCHAR(500) NOT NULL, -- Name of attribute `dataType` INT NOT NULL, -- The type of data the attribute holds (int, date, string, etc.) `data` NVARCHAR(500) NOT NULL, -- Value of attribute `lastModifiedBy` VARBINARY(16), -- User UUID & FK `lastModified` DATETIME NOT NULL, -- Last time the record was updated PRIMARY KEY (`iD`), FOREIGN KEY (`libraryID`) REFERENCES Library(`iD`) ON DELETE CASCADE, INDEX (`name`) ) ENGINE = MYISAM; ALTER TABLE `Users` ADD CONSTRAINT FK_User_Library FOREIGN KEY (`libraryID`) REFERENCES Library(`iD`); -- Example Data INSERT INTO `Library` VALUES(0x01, 'People', 'text/plain', 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam pulvinar scelerisque quam, vel convallis turpis porttitor in. Curabitur pulvinar fermentum pulvinar. Mauris lorem lacus, gravida porta lacinia vitae, dictum ac eros. Aliquam magna arcu, lacinia ac dictum sed, euismod eu elit. Sed semper nulla at velit pulvinar in vehicula risus tempus. Phasellus id nisl libero, id porttitor purus. Integer aliquet semper aliquam. Morbi elit mi, pellentesque et ornare nec, iaculis gravida elit. Sed in luctus lorem. Maecenas a purus at lectus condimentum congue.', NULL, NULL, NULL, '2011-11-16 20:27:54'); INSERT INTO `Library` VALUES(0x02, 'Jane Doe', 'text/x-markup', 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam pulvinar scelerisque quam, vel convallis turpis porttitor in. Curabitur pulvinar fermentum pulvinar. Mauris lorem lacus, gravida porta lacinia vitae, dictum ac eros. Aliquam magna arcu, lacinia ac dictum sed, euismod eu elit. Sed semper nulla at velit pulvinar in vehicula risus tempus. Phasellus id nisl libero, id porttitor purus. Integer aliquet semper aliquam. Morbi elit mi, pellentesque et ornare nec, iaculis gravida elit. Sed in luctus lorem. Maecenas a purus at lectus condimentum congue.', NULL, NULL, NULL, '2011-11-16 20:29:13'); INSERT INTO `Library` VALUES(0x03, 'Younger Years', 'text/x-markup', 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam pulvinar scelerisque quam, vel convallis turpis porttitor in. Curabitur pulvinar fermentum pulvinar. Mauris lorem lacus, gravida porta lacinia vitae, dictum ac eros. Aliquam magna arcu, lacinia ac dictum sed, euismod eu elit. Sed semper nulla at velit pulvinar in vehicula risus tempus. Phasellus id nisl libero, id porttitor purus. Integer aliquet semper aliquam. Morbi elit mi, pellentesque et ornare nec, iaculis gravida elit. Sed in luctus lorem. Maecenas a purus at lectus condimentum congue.', 0x02, 1, NULL, '2011-11-16 00:00:00'); INSERT INTO `Library` VALUES(0x04, 'College Years', 'text/x-markup', 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam pulvinar scelerisque quam, vel convallis turpis porttitor in. Curabitur pulvinar fermentum pulvinar. Mauris lorem lacus, gravida porta lacinia vitae, dictum ac eros. Aliquam magna arcu, lacinia ac dictum sed, euismod eu elit. Sed semper nulla at velit pulvinar in vehicula risus tempus. Phasellus id nisl libero, id porttitor purus. Integer aliquet semper aliquam. Morbi elit mi, pellentesque et ornare nec, iaculis gravida elit. Sed in luctus lorem. Maecenas a purus at lectus condimentum congue.', 0x02, 2, NULL, '2011-11-16 20:31:52'); INSERT INTO `Library` VALUES(0x05, 'Yale', 'text/x-markup', 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam pulvinar scelerisque quam, vel convallis turpis porttitor in. Curabitur pulvinar fermentum pulvinar. Mauris lorem lacus, gravida porta lacinia vitae, dictum ac eros. Aliquam magna arcu, lacinia ac dictum sed, euismod eu elit. Sed semper nulla at velit pulvinar in vehicula risus tempus. Phasellus id nisl libero, id porttitor purus. Integer aliquet semper aliquam. Morbi elit mi, pellentesque et ornare nec, iaculis gravida elit. Sed in luctus lorem. Maecenas a purus at lectus condimentum congue.', 0x04, 2, NULL, '2011-11-16 20:32:44'); INSERT INTO `Library` VALUES(0x06, 'Old Age', 'text/x-markup', 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam pulvinar find me here scelerisque quam, vel convallis turpis porttitor in. Curabitur pulvinar fermentum pulvinar. Mauris lorem lacus, gravida porta lacinia vitae, dictum ac eros. Aliquam magna arcu, lacinia ac dictum sed, euismod eu elit. Sed semper nulla at velit pulvinar in vehicula risus tempus. Phasellus id nisl libero, id porttitor purus. Integer aliquet semper aliquam. Morbi elit mi, pellentesque et ornare nec, iaculis gravida elit. Sed in luctus lorem. Maecenas a purus at lectus condimentum congue.', 0x02, 3, NULL, '2011-11-16 20:31:52'); INSERT INTO `Library` VALUES(0x07, 'Community College', 'text/x-markup', 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam pulvinar scelerisque quam, vel convallis turpis porttitor in. Curabitur pulvinar fermentum pulvinar. Mauris lorem lacus, gravida porta lacinia vitae, dictum ac eros. Aliquam magna arcu, lacinia ac dictum sed, euismod eu elit. Sed semper nulla at velit pulvinar in vehicula risus tempus. Phasellus id nisl libero, id porttitor purus. Integer aliquet semper aliquam. Morbi elit mi, pellentesque et ornare nec, iaculis gravida elit. Sed in luctus lorem. Maecenas a purus at lectus condimentum congue.', 0x04, 1, NULL, '2011-11-16 20:33:11'); INSERT INTO `Library` VALUES(0x08, 'John Doe', 'text/x-markup', 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam pulvinar scelerisque quam, vel convallis turpis porttitor in. Curabitur pulvinar fermentum pulvinar. Mauris lorem lacus, gravida porta lacinia vitae, dictum ac eros. Aliquam magna arcu, lacinia ac dictum sed, euismod eu elit. Sed semper nulla at velit pulvinar in vehicula risus tempus. Phasellus id nisl libero, id porttitor purus. Integer aliquet semper aliquam. Morbi elit mi, pellentesque et ornare nec, iaculis gravida elit. Sed in luctus lorem. Maecenas a purus at lectus condimentum congue.', NULL, NULL, NULL, '2011-11-16 20:34:40'); INSERT INTO `Library` VALUES(0x09, 'Planets', 'text/x-markup', 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam pulvinar scelerisque quam, vel convallis turpis porttitor in. Curabitur pulvinar fermentum pulvinar. Mauris lorem lacus, gravida porta lacinia vitae, dictum ac eros. Aliquam magna arcu, lacinia ac dictum sed, euismod eu elit. Sed semper nulla at velit pulvinar in vehicula risus tempus. Phasellus id nisl libero, id porttitor purus. Integer aliquet semper aliquam. Morbi elit mi, pellentesque et ornare nec, iaculis gravida elit. Sed in luctus lorem. Maecenas a purus at lectus condimentum congue.', NULL, NULL, NULL, '2011-11-16 20:27:54'); INSERT INTO `Library` VALUES(0x10, 'Earth', 'text/x-markup', 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam pulvinar scelerisque quam, vel convallis turpis porttitor in. Curabitur pulvinar fermentum pulvinar. Mauris lorem lacus, gravida porta lacinia vitae, dictum ac eros. Aliquam magna arcu, lacinia ac dictum sed, euismod eu elit. Sed semper nulla at velit pulvinar in vehicula risus tempus. Phasellus id nisl libero, id porttitor purus. Integer aliquet semper aliquam. Morbi elit mi, pellentesque et ornare nec, iaculis gravida elit. Sed in luctus lorem. Maecenas a purus at lectus condimentum congue.', NULL, NULL, NULL, '2011-11-16 20:27:54'); INSERT INTO `Library` VALUES(0x11, 'Mars', 'text/x-markup', 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam pulvinar scelerisque quam, vel convallis turpis porttitor in. Curabitur pulvinar fermentum pulvinar. Mauris lorem lacus, gravida porta lacinia vitae, dictum ac eros. Aliquam magna arcu, lacinia ac dictum sed, euismod eu elit. Sed semper nulla at velit pulvinar in vehicula risus tempus. Phasellus id nisl libero, id porttitor purus. Integer aliquet semper aliquam. Morbi elit mi, pellentesque et ornare nec, iaculis gravida elit. Sed in luctus lorem. Maecenas a purus at lectus condimentum congue.', NULL, NULL, NULL, '2011-11-16 20:27:54'); INSERT INTO `Attributes` VALUES(0x01, 0x02, 'TypeOf', 1, 0x01, NULL, '2011-11-16 20:34:40'); INSERT INTO `Attributes` VALUES(0x02, 0x02, 'BirthDate', 2, '19770521', NULL, '2011-11-16 20:34:40'); INSERT INTO `Attributes` VALUES(0x03, 0x02, 'EyeColor', 3, 'Brown', NULL, '2011-11-16 20:34:40'); INSERT INTO `Attributes` VALUES(0x04, 0x08, 'TypeOf', 1, 0x01, NULL, '2011-11-16 20:34:40'); INSERT INTO `Attributes` VALUES(0x05, 0x08, 'BirthDate', 2, '19740521', NULL, '2011-11-16 20:34:40'); INSERT INTO `Attributes` VALUES(0x06, 0x10, 'TypeOf', 1, 0x08, NULL, '2011-11-16 20:34:40'); INSERT INTO `Attributes` VALUES(0x07, 0x11, 'TypeOf', 1, 0x08, NULL, '2011-11-16 20:34:40'); 
+6
source share
1 answer

In the INSERT statement in the Libary_Update trigger, you have the following line:

 WHERE subtree.`ancestor` = NEW.`iD` 

but you are not updating the ID field, so I don’t think you will have the value NEW.iD. Should this line use OLD.iD instead?

+1
source

Source: https://habr.com/ru/post/901873/


All Articles