MySQL分层数据帮助-闭包表方法

MySQL分层数据帮助-闭包表方法,mysql,hierarchical-data,transitive-closure-table,Mysql,Hierarchical Data,Transitive Closure Table,我试图在MySQL中实现一个系统来存储分层数据。我决定从第40张幻灯片开始,按照所述实施系统。我正在尝试设置数据库,以便自动维护EntryPaths表 更新:我已经更新了数据库创建SQL。我想我已经有一半的东西在更新了。运行数据库创建SQL后,请尝试以下操作 首先看看这个条目的外观 -- Example query to return a full library entry (0x02 is the entry iD) SELECT `Library`.* FROM `Library` LEF

我试图在MySQL中实现一个系统来存储分层数据。我决定从第40张幻灯片开始,按照所述实施系统。我正在尝试设置数据库,以便自动维护
EntryPaths

更新:我已经更新了数据库创建SQL。我想我已经有一半的东西在更新了。运行数据库创建SQL后,请尝试以下操作

首先看看这个条目的外观

-- 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`
这个看起来怎么样

-- 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`
第一个条目有几个子条目,第二个条目没有子条目。运行以下更新以将“大学年”节点(及其子节点)重新分配到
John Doe

UPDATE  `Library` SET  `subsectionOf` =  0x08 WHERE  `Library`.`iD` = 0x04;
如果重新运行上述两条select语句,您将看到项目已从
Jane Doe
中删除,但它们未按预期添加到
John Doe
Library\u Update
触发器出现故障,但我没有办法尝试修复它

数据库将使用示例数据创建SQL:

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

在Libary_Update触发器中的INSERT语句中,有以下行:

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

但是您没有更新ID字段,因此我认为您不会有新的.ID值。该行是否应该改用OLD.iD

我真的认为新的是这一排的样子,旧的是这一排的样子。但是您是正确的,新的只是更新的值。呵呵,几天前一个闭包表问题变成了一个SQL错误。再次感谢并享受销售代表的乐趣。感谢我能提供的帮助,感谢你的观点……现在我可以为其他人的问题添加评论了!呜呼!我注意到您的表类型为MYISAM,但我认为这种类型不支持外键?只是好奇,谢谢你的发帖。