美文网首页
erlang-mnesia操作

erlang-mnesia操作

作者: 码农工号9527 | 来源:发表于2019-05-29 16:27 被阅读0次
    -module(test_mnesia).
    -import(lists, [foreach/2]).
    -include_lib("stdlib/include/qlc.hrl").
    -compile(export_all).
    -record(shop, {id, item, quantity, cost}).%定义shop表的表结构
    -record(items, {id, item_info}).%定义shop表的表结构
    -ifdef(debug).
    -define(LOG(X), io:format("pid:~p , {~p,~p}: ~p~n", [self(), ?MODULE, ?LINE, X])).
    -else.
    -define(LOG(X), io:format("pid:~p , {~p,~p}: ~p~n", [self(), ?MODULE, ?LINE, X])).
    -endif.
    
    do_this_once() ->
        mnesia:create_schema([node()]),
        mnesia:start(),
        %{type,set} 表示id作为主键,不允许id重复,如果改为 {type,bag},id可以重复,但整条记录不能重复
        mnesia:create_table(shop, [{attributes, record_info(fields, shop)}, {type,set}, {disc_copies, [node()]} ]),
        mnesia:create_table(items, [{attributes, record_info(fields, items)}, {type,set}, {disc_copies, [node()]} ]),
        mnesia:stop().
    
    start() ->
        mnesia:stop(),
        mnesia:start(),
        mnesia:wait_for_tables([shop], 2000),%等待应用程序需要的表初始化完成,0.002秒超时
        init_table(shop_info()).%写入数据
    
    delete_table(TabelName) ->
        mnesia:delete_table(TabelName).
    
    %方法1 获取所有数据
    get_all1(TabelName) ->
        ?LOG(TabelName),
        Qh =qlc:q([X || X <- mnesia:table(TabelName)]),%select * from TableName
        F = fun() -> qlc:e(Qh) end,%将qlc:q/1编译的查询匹配给F
        {atomic, Val} = mnesia:transaction(F),%将F拿去走事务流程
        Val. %消除atomic,只取值
      %本来结果为:
      % {atomic,[{shop,apple,20,2.3},
      %        {shop,orange,100,3.8},
      %        {shop,pear,200,3.6},
      %        {shop,banana,420,4.5}]}
      % 处理后
      %  [{shop,apple,20,2.3},
      % {shop,orange,100,3.8},
      % {shop,pear,200,3.6},
      % {shop,banana,420,4.5}]
    %方法2 简化获取所有数据
    get_all2(TabelName) ->
        F = fun() ->
            Q = qlc:q([E || E <- mnesia:table(TabelName)]),
            qlc:e(Q)
            end,
        mnesia:transaction(F).
    %方法3 获取所有数据
    get_all3(TabelName) ->
        F = fun() ->
            MatchHead = #shop{ _ = '_' },
            Guard = [],
            Result = ['$_'],
            mnesia:select(TabelName, [{MatchHead, Guard, Result}])
        end,
        mnesia:transaction(F).
    
    %start开始时插入的数据
    shop_info() ->
        [%% The shop table
            {shop, 1, apple, 20, 2.3},
            {shop, 2, orange, 100, 3.8},
            {shop, 3, pear, 200, 3.6},
            {shop, 4, banana, 420, 4.5}
        ].
    %执行start时自动操作的脏写操作,foreach从列表TableData中取出一条条执行
    init_table(TableData) ->
        F = fun(Model) -> mnesia:dirty_write(Model) end,
        lists:foreach(F, TableData).
    
    %where 方式1
    where1() ->
        F = fun() ->
            MatchHead = #shop{id = '$1', item = '$2', _ = '_' },
            Guard = [{'>', '$1', 2}],
            Result = ['$2'],
            mnesia:select(shop, [{MatchHead, Guard, Result}])
        end,
        mnesia:transaction(F).
    %where 方式2
    where2() ->
        F = fun() ->
            Q = qlc:q([E#shop.item || E <- mnesia:table(shop), E#shop.id>2]),
            qlc:e(Q)
        end,
        mnesia:transaction(F).
    % 如果查找主键 key=X 的记录 也可如下执行
    where3() ->
        F = fun() ->
            mnesia:read({shop,5})
        end,
        mnesia:transaction(F).
    % 查找非主键字段的记录 也可如下执行
    where4() ->
        F = fun() ->
            MatchHead = #shop{ id = '_', item = banana, quantity = '_', cost = '_' },
            Guard = [],
            Result = ['$_'],
            mnesia:select(shop, [{MatchHead, Guard, Result}])
        end,
        mnesia:transaction(F).
    
    % 查询部分字段 方式1
    select_some1() ->
        F = fun() ->
            MatchHead = #shop{item = '$1', quantity = '$2', _ = '_' },
            Guard = [],
            Result = ['$$'],
            mnesia:select(shop, [{MatchHead, Guard, Result}])
        end,
        mnesia:transaction(F).
    % 查询部分字段 方式2
    select_some2() ->
        F = fun() ->
            Q = qlc:q([[E#shop.item, E#shop.quantity] || E <- mnesia:table(shop)]),
            qlc:e(Q)
        end,
        mnesia:transaction(F).
    
    %===============================================
    %   select * from shop order by id asc
    %===============================================
    % order by查询 方式1
    order_by1() ->
        F = fun() ->
            Q = qlc:q([E || E <- mnesia:table(shop)]),
            % keysort(KeyPos, QH1, SortOptions) -> QH2 返回一个查询句柄。在评估查询句柄时QH2,查询句柄的答案根据选项QH1进行排序file_sorter:keysort/4。
            % keysort(KeyPos, QH1)相当于keysort(KeyPos, QH1, [])。 KeyPos元组的位置 id位于的二个位置 第一个是表名
            qlc:e(qlc:keysort(2, Q, [{order, ascending}]))
        end,
        mnesia:transaction(F).
    % order by查询 方式2
    order_by2() ->  
        F = fun() ->  
            Q = qlc:q([E || E <- mnesia:table(shop)]), 
            Order = fun(A, B) ->
                B#shop.id > A#shop.id
            end,
            qlc:e(qlc:sort(Q, [{order, Order}]))
        end,  
        mnesia:transaction(F).
    
    % join 查询
    %===============================================
    %   select items.* from shop join items on (shop.id = items.id)
    %      where shop.item = 'apple'
    %===============================================
    select_join() ->
    F = fun() ->
        Q = qlc:q([Y || X <- mnesia:table(shop),
            X#shop.item =:= apple,
            Y <- mnesia:table(items),
            X#shop.id =:= Y#items.id
        ]),
        qlc:e(Q)
    end,
    mnesia:transaction(F).
    
    %===============================================
    %   select * from shop limit 2
    %===============================================
    % Limit 查询
    select_limit2() -> 
        F = fun() ->
            Q = qlc:q([E || E <- mnesia:table(shop)]),
            QC = qlc:cursor(Q),
            qlc:next_answers(QC, 2)
        end,
        mnesia:transaction(F).
    
    % Select count(*) 查询
    select_count() ->
    F = fun() ->
        mnesia:table_info(shop, size)
    end,
    mnesia:transaction(F).
    
    %删除操作
    delete(Item) ->
        Oid = {shop, Item},
        F = fun() ->
            mnesia:delete(Oid)
        end,
        mnesia:transaction(F).
    %脏删除操作
    dirty_delete(Item) ->
        Oid = {shop, Item},
        F = fun() ->
            mnesia:dirty_delete(Oid)
        end,
        mnesia:transaction(F).
    
    %写操作
    write() ->
        Oid =  {shop, 5, potato, 2456, 1.3},
        F = fun() ->
            mnesia:write(Oid)
        end,
        mnesia:transaction(F).
    %脏写操作
    dirty_write() ->
        Oid =  {shop, 5, potato, 2456, 1.2},
        F = fun() ->
            mnesia:dirty_write(Oid)
        end,
        mnesia:transaction(F).
    % Insert / Update 操作  mnesia是根据主键去更新记录的,如果主键不存在则插入
    write_test(Args) ->
        [Id, Item, Quantity, Cost] = Args,
        F = fun() ->
            Q = #shop{id = Id, item = Item, quantity = Quantity, cost = Cost},
            mnesia:write(Q)
        end,
        mnesia:transaction(F).
    
    
    % 封装的执行增加,删除的方法,测试脏操作不支持事务  
    % 脏操作指在事务的范围以外而且没有设置任何锁来执行的操作
    % apply 执行Function传入参数为Pram  true = ok必定出错,不匹配  
    % 执行test_mnesia:execute(fun test_mnesia:delete/1,[apple]).与test_mnesia:execute(fun test_mnesia:dirty_delete/1,[apple]). 
    % 不是脏删除时,因为支持事务,执行失败  是脏删除时,因为不支持事务,执行成功 
    execute(Function,Pram) when is_function(Function),is_list(Pram) ->
        F = fun() ->
            apply(Function,Pram)
            ,true = ok  %在事物里制造问题,验证事物的有效性
        end,
        mnesia:transaction(F).
    

    参考:
    https://www.jianshu.com/p/2d43992c829c
    https://blog.csdn.net/mycwq/article/details/12158967

    相关文章

      网友评论

          本文标题:erlang-mnesia操作

          本文链接:https://www.haomeiwen.com/subject/tuiytctx.html