2011-11-19 16 views
6

Estoy tratando de implementar un sistema en MySQL para almacenar datos jerárquicos. Decidí ir con el sistema implementado here como se describe en Bill Karwin comenzando en la diapositiva 40. Estoy tratando de configurar la base de datos para que la tabla EntryPaths se mantenga automáticamente.Ayuda de datos jerárquicos MySQL - Método de tabla de cierre

Actualización: He actualizado la base de datos para crear SQL un poco. Tengo cosas 1/2 trabajando para una actualización, creo. Después de ejecutar la base de datos SQL CREATE intente lo siguiente

En primer lugar ver cómo se ve esta entrada

-- 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` 

Y cómo se ve éste

-- 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` 

La primera entrada consultados tiene varios hijos, el segundo no tiene niños. Ejecute el siguiente actualización de los Reparent nodo 'College Años (y sus hijos) a John Doe

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

Si vuelve a ejecutar las dos instrucciones select anteriores se verá que los artículos han sido retirados de Jane Doe pero tienen no se ha agregado al John Doe como se esperaba. El desencadenador Library_Update tiene la culpa, pero me estoy quedando sin ideas para tratar de solucionarlo.

La base de datos SQL crear con los datos de la muestra:

-- 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'); 
+0

Me di cuenta de que tiene un tipo de tabla como MYISAM, pero pensé que este tipo no admitía claves externas. Solo curiosidad, gracias por publicar. – dmp

Respuesta

1

En su sentencia INSERT en el gatillo Libary_Update que tiene la siguiente línea:

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

pero no se está actualizando el campo ID de modo No creo que tengas un valor NEW.iD. ¿Debería esa línea posiblemente usar OLD.iD en su lugar?

+0

Realmente pensé que NUEVA era la apariencia de la fila y VIEJA es como se veía la fila. Sin embargo, estás en lo cierto, NEW es solo los valores actualizados. Heh, pasó de ser una pregunta de tabla de cierre hace unos días a un error de SQL. Gracias de nuevo y disfruta del representante. – Justin808

+0

Gracias me alegro de poder ayudar y gracias por los puntos ... ahora puedo agregar comentarios a las preguntas de otras personas! woohoo! – Chris

Cuestiones relacionadas