如果这是一个基本问题,我道歉,但我是数据库新手。我正在使用sqlite来管理某些工具的命令行选项列表。一个简单的版本是:
sqlite> CREATE TABLE option_set (set_id INTEGER, idx INTEGER, value TEXT ); sqlite> INSERT INTO option_set VALUES( 1, 1, 'a' ); sqlite> INSERT INTO option_set VALUES( 1, 2, 'b' ); sqlite> INSERT INTO option_set VALUES( 1, 3, 'c' ); sqlite> SELECT value FROM option_set WHERE set_id=1 ORDER BY idx; a b c
一切正常。我想添加一个增强功能,但是我允许一个option_set包含另一个。例如,如果我将option_set = 2指定为{'d','e',[option_set = 1],'f'},我希望这意味着选项{'d','e','a' ,'b','c','f'}。问题是如何在数据库中表达这一点。我在考虑以下几点:
sqlite> CREATE TABLE option_set (set_id INTEGER, idx INTEGER, contained_set_id INTEGER, value TEXT ); sqlite> INSERT INTO option_set VALUES( 1, 1, NULL, 'a' ); sqlite> INSERT INTO option_set VALUES( 1, 2, NULL, 'b' ); sqlite> INSERT INTO option_set VALUES( 1, 3, NULL, 'c' ); sqlite> INSERT INTO option_set VALUES( 2, 1, NULL, 'd' ); sqlite> INSERT INTO option_set VALUES( 2, 2, NULL, 'e' ); sqlite> INSERT INTO option_set VALUES( 2, 3, 1, NULL ); sqlite> INSERT INTO option_set VALUES( 2, 4, NULL, 'f' );
这个想法是,在表的每一行中,我要么有一个值,要么应该扩展另一个set_id。问题是我不知道如何查询这样的表 - 我怎么能产生选项列表而不是递归地做选择?我并不是对包含和值列永远不会有效的结构感到疯狂,但不确定如何解决这个问题。不同的桌子设计会更好吗?
感谢。
答案 0 :(得分:2)
要进行递归查询,您需要recursive common table expression:
WITH RECURSIVE
contained_sets(level, idx, contained_set_id, value)
AS (SELECT 0, idx, contained_set_id, value
FROM option_set
WHERE set_id = 2
UNION ALL
SELECT level + 1,
option_set.idx,
option_set.contained_set_id,
option_set.value
FROM option_set
JOIN contained_sets ON option_set.set_id = contained_sets.contained_set_id
ORDER BY 1 DESC, 2)
SELECT value
FROM contained_sets
WHERE contained_set_id IS NULL;
value
----------
d
e
a
b
c
f
(这在SQLite 3.8.3或更高版本中受支持。)