ツリーをリレーショナル データベースに格納するには、いくつかのオプションがあります。概要については、Bill Karwinのスライドをお勧めします。
読み取り速度が最も重要であると述べたので、クロージャー テーブルは適切で強力なエンコーディングになります。クロージャ テーブルは、各パス (/a/b/c など) ごとにすべての親/子を (推移的に) 格納する多対多の関係です。このようにして、ツリーに対する多くのクエリを 1 つの SQL クエリで (非再帰的に) 実行できます。
それは次のようになります
create table nodes (
path varchar primary key
/* your other attributes here, can be null */
);
create table parents_children (
parent_path varchar,
child_path varchar,
primary key(parent_path,child_path),
foreign key (parent_path) references nodes (path),
foreign key (child_path) references nodes (path)
);
ディレクトリ /a/b/ の下に新しいファイル /a/b/c を挿入するには、次のようにします。
insert into nodes values ('/a/b/c');
insert into parents_children
select parent_path, '/a/b/c' from parents_children where child_path = '/a/b/'
union all select '/a/b/c','/a/b/c';
たとえば、'/a' のすべての子を再帰的にクエリするには、次のようにします。
select *
from nodes join parents_children on path = child_path
where parent_path = '/a';
次のファイル ツリーを格納する、より包括的な例:
/
/a/
/a/b/
/a/b/d
/a/c
/b
データを挿入するには:
insert into nodes values ('/');
insert into parents_children values ('/','/');
insert into nodes values ('/a/');
insert into parents_children
select parent_path, '/a/' from parents_children where child_path = '/'
union all select '/a/','/a/';
insert into nodes values ('/a/b/');
insert into parents_children
select parent_path, '/a/b/' from parents_children where child_path = '/a/'
union all select '/a/b/','/a/b/';
insert into nodes values ('/a/c');
insert into parents_children
select parent_path, '/a/c' from parents_children where child_path = '/a/'
union all select '/a/c','/a/c';
insert into nodes values ('/a/b/d');
insert into parents_children
select parent_path, '/a/b/d' from parents_children where child_path = '/a/b/'
union all select '/a/b/d','/a/b/d';
insert into nodes values ('/b');
insert into parents_children
select parent_path, '/b' from parents_children where child_path = '/'
union all select '/b','/b';
/a/ のすべての子を照会するには
select node.*
from nodes join parents_children on path = child_path
where parent_path = '/a/';
path
----------
/a/
/a/b/
/a/b/d
/a/c