mysql set s=0_mysql的串列类型之 set理解

最近对mysql的 set 串列类型有点了解,拿出来分享,有不足之处欢迎各位拍砖

1.gif

首先引入set的含义:

对于 SET 类型,SET 列的集合成员不是顺序编号的,而是每个成员对应 SET 值中的一个二进制位。

第一个集合成员对应于 0 位,第二个成员对应于 1 位,以此类推。

数值 SET 值 0 对应于空串,SET 成员以位值保存。

每个字节的 8 个集合值可按此方式存放,因此 SET 列的存储大小是由集合成员的数目决定的,最多 64 个成员。

对于大小为 1 到 8、9 到 16、17 到 24、25 到 32、33 到 64 个成员的集合,

其 SET 值分别占用 1、2、3、4 或 8 个字节。

SET 定义中的值顺序决定了在显示由多个集合成员组成的 SET 列值时,子串出现的顺序。

光看理论是不行的,还得以例子来说明:例如

我在本机建立了一个表:usage_flags(详细信息如下)

这里重点是set,先不要注意我的引擎和字符编码

mysql> showcreatetableusage_flags\G

*************************** 1. row ***************************

Table: usage_flags

CreateTable:CREATETABLE`usage_flags` (

`s`set('ls','tp','ns','nt','nb','np','nc','si','al','mr','e5','e4','no','ph')defaultNULL

) ENGINE=MyISAMDEFAULTCHARSET=latin1

1 rowinset(0.00 sec)

解释:

s 字段的类型是set,包括的值有 'ls ', 'tp ', 'ns ', 'nt ', 'nb ', 'np ', 'nc ', 'si ', 'al ', 'mr ', 'e5 ', 'e4 ', 'no ', 'ph ' (这些就是所谓的成员了);

我们来回看set的含义中一点:而是每个成员对应 SET 值中的一个二进制位

这句话的理解是:刚刚建立的s字段中包括的值(也就是'ls''ls','tp','nt'......)对应set值中的一个二进制,我们来看以下内容:

为了方便查看以下贴出来s列的十进制和二进制的形式,这样可以看出set值对应的二进制关系

mysql>selects,s+0,bin(s+0)fromusage_flags;

+-------------+------+----------------+

| s           | s+0  | bin(s+0)       |

+-------------+------+----------------+

| ls          |    1 | 1              |

| tp          |    2 | 10             |

| ns          |    4 | 100            |

| nt          |    8 | 1000           |

| nb          |   16 | 10000          |

| np          |   32 | 100000         |

| nc          |   64 | 1000000        |

| si          |  128 | 10000000       |

| al          |  256 | 100000000      |

| mr          |  512 | 1000000000     |

| e5          | 1024 | 10000000000    |

| e4          | 2048 | 100000000000   |

|no| 4096 | 1000000000000  |

| ph          | 8192 | 10000000000000 |

+-------------+------+----------------+

14rowsinset(0.00 sec)

解释:

在这里,s+0列中的数值可以等价于s列中对应的值,我们来看一个例子:

以下所查出来的内容是完全相同的,这一点可以证明上述所叙

mysql>selects,s+0,bin(s+0)fromusage_flagswheres=8;

+------+------+----------+

| s    | s+0  | bin(s+0) |

+------+------+----------+

| nt   |    8 | 1000     |

+------+------+----------+

1 rowinset(0.00 sec)

mysql>selects,s+0,bin(s+0)fromusage_flagswheres='nt';

+------+------+----------+

| s    | s+0  | bin(s+0) |

+------+------+----------+

| nt   |    8 | 1000     |

+------+------+----------+

1 rowinset(0.00 sec)

当然,这些需要运用到实际开发中才能更加深入的理解,我们再来看一个例子:

数据库已连接

if (preg_match("/admin/i",$FORM_userid)) { $sql = "SELECT * FROM userinf

WHERE UserId='$FORM_userid'

AND Password=password('$FORM_psd')

AND (UserType & 2147483648)";

} else {

$sql = "SELECT * FROM userinf

WHERE UserId='$FORM_userid'

AND Password='$FORM_psd'

AND (UserType & 1073741824)";

}

这是身份验证的一段程序。$FORM_userid和$FORM_psd'分别是上一Web页登录窗口提交的的用户名和密码。

userinf表中的UserType列类型为SET,其中的值分别为:'general','a1','a2','a3','a4','a5','a6','a7','b0','b1','b2','b3',

'b4','b5','b6','b7','c0','c1','c2','c3','c4','c5','c6','c7','d0','d1','d2','d3','d4',

'd5','nostop','admin'。

请问,(UserType & 2147483648)和(UserType & 1073741824)分别代表什么含义,为什么?

为了解答这个例子,我们按照上面所说的步骤来做;

首先,我们来建立一个userinf表和usertype字段并且该类型为set:

mysql> showcreatetableuserinf\G

*************************** 1. row ***************************

Table: userinf

CreateTable:CREATETABLE`userinf` (

`usertype`set('general','a1','a2','a3','a4','a5','a6','a7','b0','b1','b2','b3','b4','b5','b6','b7','c0','c1','c2','c3','c4','c5','c6','c7','d0','d1','d2','d3','d4','d5','nostop','admin')defaultNULL

) ENGINE=MyISAMDEFAULTCHARSET=latin1

1 rowinset(0.00 sec)

然后,我们再查看对应的十进制和二进制关系:

mysql>selectusertype,usertype+0,bin(usertype+0)fromuserinf;

+---------+------------+----------------------------------+

| usertype| usertype+0 | bin(usertype+0)                  |

+---------+------------+----------------------------------+

| general |          1 | 1                                |

| a1      |          2 | 10                               |

| a2      |          4 | 100                              |

| a3      |          8 | 1000                             |

| a4      |         16 | 10000                            |

| a5      |         32 | 100000                           |

| a6      |         64 | 1000000                          |

| a7      |        128 | 10000000                         |

| b0      |        256 | 100000000                        |

| b1      |        512 | 1000000000                       |

| b2      |       1024 | 10000000000                      |

| b3      |       2048 | 100000000000                     |

| b4      |       4096 | 1000000000000                    |

| b5      |       8192 | 10000000000000                   |

| b6      |      16384 | 100000000000000                  |

| b7      |      32768 | 1000000000000000                 |

| c0      |      65536 | 10000000000000000                |

| c1      |     131072 | 100000000000000000               |

| c2      |     262144 | 1000000000000000000              |

| c3      |     524288 | 10000000000000000000             |

| c4      |    1048576 | 100000000000000000000            |

| c5      |    2097152 | 1000000000000000000000           |

| c6      |    4194304 | 10000000000000000000000          |

| c7      |    8388608 | 100000000000000000000000         |

| d0      |   16777216 | 1000000000000000000000000        |

| d1      |   33554432 | 10000000000000000000000000       |

| d2      |   67108864 | 100000000000000000000000000      |

| d3      |  134217728 | 1000000000000000000000000000     |

| d4      |  268435456 | 10000000000000000000000000000    |

| d5      |  536870912 | 100000000000000000000000000000   |

| nostop  | 1073741824 | 1000000000000000000000000000000  |

| admin   | 2147483648 | 10000000000000000000000000000000 |

+---------+------------+----------------------------------+

32rowsinset(0.00 sec)

我们再回头看看这个例子的问题:

请问,(UserType & 2147483648)和(UserType & 1073741824)分别代表什么含义?

在这里有必要说一下这里的"&"的含义,很多朋友认为是连字符,其实不是的,这里的&属于位运算符,大概意思是:按位AND(与)如果两个操作数的对应位为1,则结果位为1,也就是说两个值相等则返回该对应的位,不等就不返回,意思有点类似于逻辑运算符"&&",和'&'一起的位运算符还有'|","<>"这些运算符的含义可以去google一下,我们再回到问题,来看下面结果:

mysql>selectusertype,usertype+0,bin(usertype+0)fromuserinfwhereusertype= 2147483648;

+----------+------------+----------------------------------+

| susertype| usertypes+0| bin(usertype+0)                  |

+----------+------------+----------------------------------+

| admin  | 2147483648 | 10000000000000000000000000000000 |

+----------+------------+----------------------------------+

1 rowinset(0.00 sec)

看出来了吗?UserType & 2147483648 要找的其实是 admin,同样的UserType & 1073741824要找的是nostop(注意看我两种where的写法一个是=,一个是位运算符(&):

mysql>selectusertype,usertype+0,bin(usertype+0)fromuserinfwhereusertype&1073741824;

+--------+------------+---------------------------------+

| s      | s+0        | bin(s+0)                        |

+--------+------------+---------------------------------+

| nostop | 1073741824 | 1000000000000000000000000000000 |

+--------+------------+---------------------------------+

1 rowinset(0.00 sec)

在这些值里面('general','a1','a2','a3'....)我们可以找很多只要这些值('general','a1','a2','a3')能组合起来的字符,比如说我们找usertype&108字符:

mysql>selectusertype,usertype+0,bin(usertype+0)fromuserinfwhereusertype&108;

| usertype | usertype+0  | bin(usertype+0) |

+-------------+-------------+-----------------+

| a2    |    4 | 100     |

| a3    |    8 | 1000  |

| a5    |   32 | 100000    |

| a6    |   64 | 1000000  |

+------+------+-------------------------------+

4rowsinset(0.00 sec)+-------------+-------------+--------------- -+

这样我们找到了a2+a3+a5+a6=108组合的字符了(a2,a3,a5,a6)。

有不足之处希望各路高手指点,谢谢

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值