Här är ett förslag på lösning av proceduren Storestructure() med lite testkod. Det finns massor av optimeringar att göra om man vill det, men det har jag inte ens funderat på ännu. Detta löser i vart fall TS problem, om jag fattat det rätt.
Jag har kört med MySQL Workbench CE for Windows version 5.2.47 revision 10398.
SHOW VARIABLES LIKE "%version%"; -- Ger följande resultat....
innodb_version 1.1.8
protocol_version 10
slave_type_conversions
version 5.5.29
version_comment MySQL Community Server (GPL)
version_compile_machine x86
version_compile_os Win32
DDL-script för tabellen "katalog":
Kod:
delimiter $$
CREATE TABLE `katalog`
(
`id` int(11) NOT NULL AUTO_INCREMENT,
`parent_id` int(11) DEFAULT NULL,
`name` varchar(45) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `katalog_parent_id_idx` (`parent_id`),
CONSTRAINT `katalog_parent_id` FOREIGN KEY (`parent_id`) REFERENCES `katalog` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION
) ENGINE=InnoDB DEFAULT CHARSET=latin1$$
SP: StoreStructure()
Kod:
-- --------------------------------------------------------------------------------
-- Routine DDL
-- Note: comments before and after the routine body will not be stored by the server
-- --------------------------------------------------------------------------------
DELIMITER $$
CREATE DEFINER=`root`@`localhost` PROCEDURE `StoreStructure`(path varchar(255), delim varchar(12))
BEGIN
DECLARE done INT DEFAULT FALSE;
DECLARE RowCount int;
DECLARE RowPtr int;
DECLARE katalog_id int;
DECLARE katalog_parent_id int;
DECLARE next_parent_id int;
DECLARE split_name varchar(45);
set RowPtr=0;
call splitter(path, delim);
select count(*) INTO RowCount FROM _splitresults;
WHILE RowCount > RowPtr DO
select split_value INTO split_name FROM _splitresults ORDER BY id ASC LIMIT RowPtr,1;
-- Om det inte finns någon split_parent_id så är det en root-nivå
IF next_parent_id is null THEN
select id INTO katalog_id from katalog WHERE parent_id is null AND `name`= split_name;
-- Kolla om namnet finns i databasen sedan tidigare på rootnivån
IF katalog_id is null THEN
-- Om den inte finns i databasen på root-nivå så är det bara att lägga till den
INSERT INTO katalog(`name`) VALUES (split_name);
END IF;
-- Läs upp den från databasen för att få tag i databasens id
select id, parent_id INTO katalog_id, katalog_parent_id from katalog WHERE parent_id is null AND `name`= split_name;
ELSE
-- Eftersom det finns en split_parent_id så är det en child-nivå
select id INTO katalog_id from katalog WHERE parent_id = next_parent_id AND `name`= split_name;
-- Kolla om namnet finns i databasen sedan tidigare på denna child-nivå
IF katalog_id is null THEN
-- Posten finns inte sedan tidigare
-- Om den inte finns i databasen på root-nivå så är det bara att lägga till den
INSERT INTO katalog(`parent_id`, `name`) VALUES (next_parent_id, split_name);
END IF;
-- Läs upp den från databasen för att få tag i databasens id
select id, parent_id INTO katalog_id, katalog_parent_id from katalog WHERE parent_id = next_parent_id AND `name`= split_name;
END IF;
-- Här måste vi ta vara på katalog_id för det blir parent_id för nästa nivå
set next_parent_id=katalog_id;
set katalog_id = null;
set katalog_parent_id = null;
set RowPtr = RowPtr + 1;
END WHILE;
END
Testkod:
Kod:
use wn;
call StoreStructure_Delete();
call StoreStructure('olle11/kalle12/anna13','/');
call StoreStructure('kalle21/anna22/olle23','/');
call StoreStructure('anna31/olle32/kalle33','/');
call StoreStructure('olle11/sara12/greta13','/');
call StoreStructure('kalle21/anna22/gunnar23','/');
call StoreStructure('anna31/rune32/kalle33','/');
call StoreStructure('lena31/olle32/sara33','/');
select * from katalog;
select parent_id from katalog;
select parent_id from katalog WHERE NOT PARENT_ID IS NULL;