mysql的串列類型之 set理解

 


最近對mysql的 set 串列類型有點了解,拿出來分享,有不足之處歡迎各位拍磚

 


首先引入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,先不要注意我的引擎和字符編碼

  1. mysql> show create table usage_flags\G  
  2. *************************** 1. row ***************************  
  3.        Table: usage_flags  
  4. Create TableCREATE TABLE `usage_flags` (  
  5.   `s` set('ls','tp','ns','nt','nb','np','nc','si','al','mr','e5','e4','no','ph'default NULL 
  6. ) ENGINE=MyISAM DEFAULT CHARSET=latin1  
  7. 1 row in set (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值對應的二進制關係

  1. mysql> select s,s+0,bin(s+0) from usage_flags;  
  2. +-------------+------+----------------+  
  3. | s           | s+0  | bin(s+0)       |  
  4. +-------------+------+----------------+  
  5. | ls          |    1 | 1              |   
  6. | tp          |    2 | 10             |   
  7. | ns          |    4 | 100            |   
  8. | nt          |    8 | 1000           |   
  9. | nb          |   16 | 10000          |   
  10. | np          |   32 | 100000         |   
  11. | nc          |   64 | 1000000        |   
  12. | si          |  128 | 10000000       |   
  13. | al          |  256 | 100000000      |   
  14. | mr          |  512 | 1000000000     |   
  15. | e5          | 1024 | 10000000000    |   
  16. | e4          | 2048 | 100000000000   |   
  17. no          | 4096 | 1000000000000  |   
  18. | ph          | 8192 | 10000000000000 |      
  19. +-------------+------+----------------+  
  20. 14 rows in set (0.00 sec) 

解釋:

在這裏,s+0列中的數值可以等價於s列中對應的值,我們來看一個例子:

以下所查出來的內容是完全相同的,這一點可以證明上述所敘

  1.  
  2. mysql> select s,s+0,bin(s+0) from usage_flags where s=8;   
  3. +------+------+----------+  
  4. | s    | s+0  | bin(s+0) |  
  5. +------+------+----------+  
  6. | nt   |    8 | 1000     |   
  7. +------+------+----------+  
  8. 1 row in set (0.00 sec)  
  9.  
  10. mysql> select s,s+0,bin(s+0) from usage_flags where s='nt';  
  11. +------+------+----------+  
  12. | s    | s+0  | bin(s+0) |  
  13. +------+------+----------+  
  14. | nt   |    8 | 1000     |   
  15. +------+------+----------+  
  16. 1 row in set (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:

  1. mysql> show create table userinf\G  
  2. *************************** 1. row ***************************  
  3.        Table: userinf  
  4. Create TableCREATE TABLE `userinf` (  
  5.   `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'default NULL 
  6. ) ENGINE=MyISAM DEFAULT CHARSET=latin1  
  7. 1 row in set (0.00 sec) 

然後,我們再查看對應的十進制和二進制關係:

  1. mysql> select usertype,usertype+0,bin(usertype+0) from userinf;  
  2. +---------+------------+----------------------------------+  
  3. | usertype| usertype+0 | bin(usertype+0)                  |  
  4. +---------+------------+----------------------------------+  
  5. | general |          1 | 1                                |   
  6. | a1      |          2 | 10                               |   
  7. | a2      |          4 | 100                              |   
  8. | a3      |          8 | 1000                             |   
  9. | a4      |         16 | 10000                            |   
  10. | a5      |         32 | 100000                           |   
  11. | a6      |         64 | 1000000                          |   
  12. | a7      |        128 | 10000000                         |   
  13. | b0      |        256 | 100000000                        |   
  14. | b1      |        512 | 1000000000                       |   
  15. | b2      |       1024 | 10000000000                      |   
  16. | b3      |       2048 | 100000000000                     |   
  17. | b4      |       4096 | 1000000000000                    |   
  18. | b5      |       8192 | 10000000000000                   |   
  19. | b6      |      16384 | 100000000000000                  |   
  20. | b7      |      32768 | 1000000000000000                 |   
  21. | c0      |      65536 | 10000000000000000                |   
  22. | c1      |     131072 | 100000000000000000               |   
  23. | c2      |     262144 | 1000000000000000000              |   
  24. | c3      |     524288 | 10000000000000000000             |   
  25. | c4      |    1048576 | 100000000000000000000            |   
  26. | c5      |    2097152 | 1000000000000000000000           |   
  27. | c6      |    4194304 | 10000000000000000000000          |   
  28. | c7      |    8388608 | 100000000000000000000000         |   
  29. | d0      |   16777216 | 1000000000000000000000000        |   
  30. | d1      |   33554432 | 10000000000000000000000000       |   
  31. | d2      |   67108864 | 100000000000000000000000000      |   
  32. | d3      |  134217728 | 1000000000000000000000000000     |   
  33. | d4      |  268435456 | 10000000000000000000000000000    |   
  34. | d5      |  536870912 | 100000000000000000000000000000   |   
  35. | nostop  | 1073741824 | 1000000000000000000000000000000  |   
  36. | admin   | 2147483648 | 10000000000000000000000000000000 |   
  37. +---------+------------+----------------------------------+  
  38. 32 rows in set (0.00 sec) 

我們再回頭看看這個例子的問題:

請問,(UserType & 2147483648)和(UserType & 1073741824)分別代表什麼含義?

在這裏有必要說一下這裏的"&"的含義,很多朋友認爲是連字符,其實不是的,這裏的&屬於位運算符,大概意思是:按位AND(與)如果兩個操作數的對應位爲1,則結果位爲1,也就是說兩個值相等則返回該對應的位,不等就不返回,意思有點類似於邏輯運算符"&&",和'&'一起的位運算符還有'|","<<",">>"這些運算符的含義可以去google一下,我們再回到問題,來看下面結果:

  1. mysql> select usertype,usertype+0,bin(usertype+0) from userinf where usertype= 2147483648;  
  2. +----------+------------+----------------------------------+  
  3. | susertype| usertypes+0| bin(usertype+0)                  |  
  4. +----------+------------+----------------------------------+  
  5. | admin  | 2147483648 | 10000000000000000000000000000000 |   
  6. +----------+------------+----------------------------------+  
  7. 1 row in set (0.00 sec) 

看出來了嗎?UserType & 2147483648 要找的其實是 admin,同樣的UserType & 1073741824要找的是nostop(注意看我兩種where的寫法一個是=,一個是位運算符(&):

  1. mysql> select usertype,usertype+0,bin(usertype+0) from userinf where usertype&1073741824;  
  2. +--------+------------+---------------------------------+  
  3. | s      | s+0        | bin(s+0)                        |  
  4. +--------+------------+---------------------------------+  
  5. | nostop | 1073741824 | 1000000000000000000000000000000 |   
  6. +--------+------------+---------------------------------+  
  7. 1 row in set (0.00 sec) 

在這些值裏面('general','a1','a2','a3'....)我們可以找很多隻要這些值('general','a1','a2','a3')能組合起來的字符,比如說我們找usertype&108字符:

    • mysql> select usertype,usertype+0,bin(usertype+0) from userinf where usertype&108;  
    •  
    • | usertype | usertype+0  | bin(usertype+0) |  
    • +-------------+-------------+-----------------+  
    • | a2    |    4 | 100     |   
    • | a3    |    8 | 1000  |   
    • | a5    |   32 | 100000    |   
    • | a6    |   64 | 1000000  |   
    • +------+------+-------------------------------+  
    • rows in set (0.00 sec) 
    +-------------+-------------+--------------- -+  

這樣我們找到了a2+a3+a5+a6=108組合的字符了(a2,a3,a5,a6)。

有不足之處希望各路高手指點,謝謝

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章