• 数据库状态标识位flag设计


    设计目的

    • 减少各种状态值字段
    • 减少数据库冗余和存储空间
    • 增加状态值时可灵活调整,无需增加额外字段

    运用场景

    例子1:管理用户的支付方式

    比如针对不同用户组设置了不同的支付方式支持,假设支付方式有支付宝微信银联借条等。A用户支持支付宝、微信;B用户支持支付宝、微信、借条。一般用户支付方式数据库设计为:

    ID name alipay weixin union iou
    1 A 1 1 0 0
    2 B 1 1 0 1

    这时如果后续多了其它支付方式后,就需要调整表结构增加字段,如快钱、货到付款等。这种设计方式明显不符合数据库设计第一范式,增加了很多冗余字段和存储空间。

    例子2:设置用户的操作权限

    比如有一组权限列表,查看编辑发布删除,数据库可能会是这样:

    ID name is_visible is_editble is_publishable is_deleteable
    1 A 1 1 0 0
    2 B 1 1 1 1

    上面只是举些例子来说明一个问题,当一张表的字段里包含很多这些状态值01时,我们可以使用二进制的方式来表示,而且只需要一个字段就好了。

    设计思路

    比如例1中的支付方式,假设我们最多可设计有10种支付方式。

    字段仍设为int整形,A支持支付宝、微信,则值为12(1100);B支持支付宝、微信、借条,则值为13(1101),表结构如下:

    ID name pay_flag
    1 A 12
    2 B 13

    如果增加了货到付款,可再赋值给二进制的第五位,其它位还是保持不变。

    这时候会涉及到数据库查询问题,比如上面的值12、13都支持支付宝、微信,还有14(1110)、15(1111)也支持,如果增加了二进制第五位,那么会有更多匹配值,如30(11110)、28(11100)等...
    如果要查询支持支付宝、微信的数据怎么办?这时只需要通过“位”的与运算,就能简单的查询出想要数据:

    select * from user_pay where pay_flag & b'1100';
    # 或者:  
    select * from user_pay where pay_flag & 12;
    

    php简单实现

    class PayFlag {
        const ALIPAY = 8; //01000
        const WEIXIN = 4; //00100
        const UNION  = 2; //00010
        const IOU    = 1; //00001
    
        function addFlag($old_flag, $flag) {
            return $old_flag | $flag;
        }
    
        function delFlag($old_flag, $flag) {
            return $old_flag ^ $flag;
        } 
    }
    
    $old_flag = 6; //00110
    $PayFlag = new PayFlag;
    
    //原有值 - 输出 6:110
    echo($old_flag  . ":" . decbin($old_flag) . PHP_EOL);
    
    //增加ALIPAY - 输出 14:1110
    $new_flag = $PayFlag->addFlag($old_flag, PayFlag::ALIPAY);
    echo($new_flag . ":" . decbin($new_flag) . PHP_EOL);
    
    //移除ALIPAY - 输出 6:110
    $new_flag = $PayFlag->delFlag($new_flag, PayFlag::ALIPAY);
    echo($new_flag . ":" . decbin($new_flag) . PHP_EOL);
    
    //移除UNION - 输出 4:100
    $new_flag = $PayFlag->delFlag($new_flag, PayFlag::UNION);
    echo($new_flag . ":" . decbin($new_flag) . PHP_EOL);
    
    //增加IOU - 输出 5:101
    $new_flag = $PayFlag->delFlag($new_flag, PayFlag::IOU);
    echo($new_flag . ":" . decbin($new_flag) . PHP_EOL);
    
  • 相关阅读:
    PyQt作品 – PingTester – 多点Ping测试工具
    关于和技术人员交流的一二三
    Pyjamas Python Javascript Compiler, Desktop Widget Set and RIA Web Framework
    Hybrid Qt applications with PySide and Django
    pyjamas build AJAX apps in Python (like Google did for Java)
    PyQt 维基百科,自由的百科全书
    InfoQ:请问为什么仍要选择Java来处理后端的工作?
    Eric+PyQt打造完美的Python集成开发环境
    python select module select method introduce
    GUI Programming with Python: QT Edition
  • 原文地址:https://www.cnblogs.com/gouyg/p/mysql-flag-php.html
Copyright © 2020-2023  润新知