【问题标题】:Erlang Mnesia Equivalent of SQL Select FROM WHERE Field IN (value1, value2, value3, ...)Erlang Mnesia 等价于 SQL Select FROM WHERE Field IN (value1, value2, value3, ...)
【发布时间】:2011-02-24 00:30:12
【问题描述】:

我有一个 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 中做到这一点?

【问题讨论】:

    标签: database select erlang mnesia


    【解决方案1】:

    如果您需要“复杂”的查询,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。

    【讨论】:

      【解决方案2】:

      对于这个问题的匹配规范解决方案,如果 QLC 被测量为不够有效。

      > ets:fun2ms(fun ({_,X}=E) when X == a -> E end).
      [{{'_','$1'},[{'==','$1',a}],['$_']}]
      

      ets:fun2ms 是一个解析转换,可以将 some 乐趣转换为 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}]
      

      【讨论】:

        【解决方案3】:

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

        【讨论】:

        • 感谢@Hynek -Pichi- Vychodil。这种 erlang 语法对我来说非常难看。新手很难掌握
        猜你喜欢
        • 2015-05-07
        • 2015-04-14
        • 1970-01-01
        • 2011-04-06
        • 2010-09-25
        • 2010-09-18
        • 1970-01-01
        • 1970-01-01
        • 2011-01-27
        相关资源
        最近更新 更多