我有一个mnesia表,字段为f1,f2,f3。现在,如果我选择字段值为V1的所有行,我将使用mnesia:select
并匹配规范或简单的mnesia:match_object
。现在我需要选择具有V1,V2,V3 ...或Vn(任意长度的列表)的所有行作为字段f1的值。在SQL中我会做类似
SELECT * FROM tablename WHERE f3 IN (V1, V2, V3, ... , Vn)
我如何在mnesia中这样做?
答案 0 :(得分:6)
对于此问题的匹配规范解决方案,如果测量的QLC不够有效。
> ets:fun2ms(fun ({_,X}=E) when X == a -> E end).
[{{'_','$1'},[{'==','$1',a}],['$_']}]
ets:fun2ms是一个解析变换,可以将一些乐趣转换为matchspec值。我用它作为获得我想要的matchspec的快速方法。我们得到一个matchspec列表,找到第二个元素为a的元组。我们可以将其重复用于其他键。
所以让我们用一些东西来填充ets表来试试这个,然后创建一个matchspec,它只匹配第二个元素为'a'或'c'的项目。 (我输入这个
ets:new(foo, [named_table]).
ets:insert(foo, [{1,a},{2,b},{3,c},{4,d}]).
Vs = [a,c].
MS = [{{'_','$1'},[{'==','$1',V}],['$_']} || V <- Vs].
ets:select(foo, MS).
当我跑步时,我得到:
[{1,a},{3,c}]
答案 1 :(得分:4)
Christian指出了很好的解决方案,但它可以做得更简单
2> ets:fun2ms(fun ({_,a}=E) -> E end).
[{{'_',a},[],['$_']}]
所以为了匹配你可以制作更简单的匹配规范
4> ets:new(foo, [named_table]).
foo
5> ets:insert(foo, [{1,a},{2,b},{3,c},{4,d}]).
true
6> Vs = [a,c].
[a,c]
7> MS = [{{'_',V},[],['$_']} || V <- Vs].
[{{'_',a},[],['$_']},{{'_',c},[],['$_']}]
8> ets:select(foo, MS).
[{1,a},{3,c}]
答案 2 :(得分:2)
如果您需要“复杂”查询,那么QLC是一种简洁的方式来陈述它们。 QLC是一种解析转换,允许您在各种表上使用列表推导语法,包括mnesia表。
必须具有以下内容,因为它启用了在此源文件中使QLC成为可能的解析转换。
-include_lib("stdlib/include/qlc.hrl").
基本查询表单如下所示,创建查询句柄,然后评估查询。
QH = qlc:q([X || X <- Xs]),
qlc:eval(QH).
然后,您可以使用http://www.erlang.org/doc/man/mnesia.html#table-1在mnesia表中获取后端的QLC表。因此,您的查询可以实现如下:
Vs = [V1,V2,...Vn],
QH = qlc:q([X || X <- mnesia:table(tablename),
lists:member(X#tablename.f3, Vs)]),
qlc:eval(QH).
这需要进行表扫描,效率不高。如果你在f3列上有一个索引,那么你可以改为转向它并首先查询f3 = V1,然后是V2等的条目......并合并结果。
PS
另一种方法是从V值列表中创建一个非常复杂的匹配规范并运行mnesia:select。