2011-11-19 21 views
6

Tôi đang cố triển khai một hệ thống trong MySQL để lưu trữ dữ liệu phân cấp. Tôi đã quyết định đi với hệ thống được thực hiện here như được mô tả bởi Bill Karwin bắt đầu từ số trang trình bày 40. Tôi đang cố thiết lập cơ sở dữ liệu để bảng EntryPaths được duy trì tự động.Trợ giúp về dữ liệu phân cấp MySQL - Phương pháp Bảng đóng cửa

Cập nhật: Tôi đã cập nhật cơ sở dữ liệu tạo SQL một chút. Tôi nghĩ có một số thứ làm việc để cập nhật, tôi nghĩ vậy. Sau khi chạy cơ sở dữ liệu tạo SQL thử như sau

Đầu tiên xem như thế nào cụm từ này trông

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

Và làm thế nào một điều này có vẻ

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

Mục 1 xem có một số trẻ em, thứ hai không có bọn trẻ. Chạy nâng cấp sau để reparent nút của năm Cao đẳng '(và con của nó) để John Doe

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

Nếu bạn tái chạy hai câu chọn ở trên, bạn sẽ thấy rằng mục đã bị xóa từ Jane Doe nhưng họ có chưa được thêm vào John Doe như mong đợi. Trình kích hoạt Library_Update có lỗi nhưng tôi đang hết ý tưởng để cố khắc phục.

Cơ sở dữ liệu SQL tạo với dữ liệu mẫu:

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

Tôi nhận thấy bạn có loại bảng là MYISAM - nhưng tôi nghĩ loại này không hỗ trợ khóa ngoại? Chỉ tò mò, cảm ơn vì đã đăng bài. – dmp

Trả lời

1

Trong tuyên bố INSERT của bạn trong cò Libary_Update bạn có dòng sau:

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

nhưng bạn không cập nhật các trường ID để Tôi không nghĩ rằng bạn sẽ có một giá trị NEW.iD. Nếu dòng đó có thể sử dụng OLD.iD thay thế?

+0

Tôi thực sự nghĩ rằng NEW là hàng sẽ trông như thế nào và OLD là hàng trông như thế nào. Bạn là chính xác mặc dù, mới chỉ là giá trị cập nhật. Heh, đã thay đổi từ một câu hỏi bảng đóng cửa vài ngày trước thành một lỗi SQL. Cảm ơn một lần nữa và tận hưởng đại diện. – Justin808

+0

Cảm ơn rất vui vì tôi có thể giúp đỡ và cảm ơn cho các điểm ... bây giờ tôi có thể thêm ý kiến ​​cho các câu hỏi của người khác! woohoo! – Chris

Các vấn đề liên quan