【问题标题】:MySQL enum vs. setMySQL 枚举与集合
【发布时间】:2013-01-25 16:23:35
【问题描述】:

对于 MySQL 数据类型的“enum”和“set”,使用一个和另一个有什么区别和优缺点?

示例数据类型:

  • 枚举('A', 'B', 'C')
  • set('A', 'B', 'C')

我知道的唯一区别是 ENUM 只允许选择一个值,而 SET 允许选择多个值。

【问题讨论】:

  • 没有推荐/不推荐。您应该根据自己的要求选择其中之一。
  • 这两种类型无关。您不妨问一下哪个更好 - int 还是 text?

标签: mysql database


【解决方案1】:

正如MySQL documentation 所说:

ENUM 或 SET 列的定义确实作为值的约束 入列。不存在的值会发生错误 满足这些条件:

ENUM 值必须是列定义中列出的值之一,或者 其内部数字等价物。该值不能是错误 值(即 0 或空字符串)。对于定义为的列 ENUM('a','b','c'), '', 'd', 或 'ax' 等值是非法的并且是 被拒绝。

SET 值必须是空字符串或仅由 列定义中列出的值,以逗号分隔。为一个 列定义为 SET('a','b','c'),值如 'd' 或 'a,b,c,d' 是非法的并被拒绝。

【讨论】:

  • 注意! (a, b, c, d) 的值不会被拒绝。只有d 将被拒绝,从而导致值(a, b, c)
  • 这可能是官方文档,但它仍然是一种非常混乱的描述方式。根据其他答案,差异变得清晰。 SET 是一个 ENUM 数组,其中每个值由 0 个或多个枚举样式值组成。
  • 这不是一个好的答案。要求清楚地解释差异和缺点/优点;官方文档,其中这个答案只是一个副本,没有这样做。
  • (a, b, c, d) 如果开启 Strict 模式将被拒绝
  • 这不是答案。
【解决方案2】:

Enum 和 Set 完全取决于要求,例如,如果您有一个单选按钮列表,一次只能选择一个,请使用 Enum。如果您有一个复选框列表,其中一次可以选择多个项目,请使用 set。

【讨论】:

    【解决方案3】:
    CREATE TABLE setTest(
      attrib SET('bold','italic','underline')
    );
    
    INSERT INTO setTest (attrib) VALUES ('bold');
    INSERT INTO setTest (attrib) VALUES ('bold,italic');
    INSERT INTO setTest (attrib) VALUES ('bold,italic,underline');
    

    你可以把上面的代码复制粘贴到mysql中,你会发现SET其实是一个集合。您可以存储您声明的每个属性组合。

    CREATE TABLE enumTest(
     color ENUM('red','green','blue')
    );
    
    INSERT INTO enumTest (color) VALUES ('red');
    INSERT INTO enumTest (color) VALUES ('gray');
    INSERT INTO enumTest (color) VALUES ('red,green');
    

    您也可以复制上面的代码。而且你会发现每个ENUM实际上每次只能存储一次。你会发现最后两行的结果都是空的。

    【讨论】:

      【解决方案4】:

      类比:
      ENUM = 单选字段(仅接受的值是列出的值,只能选择一个)
      SET = 复选框字段(仅接受的值是列出的值,可以选择多个)

      【讨论】:

      • 简洁易懂!
      • 这是正确的区别,描述得很清楚。谢谢@Brad Kent
      【解决方案5】:

      其实很简单:

      当您定义 ENUM('Yes', 'No', 'Maybe') 时,您必须仅插入其中一个值(或它们的位置索引号)

      当您定义 SET('R', 'W', 'X') 时,您可以插入一个空字符串, 这些值中的一个或多个。如果您插入不在预定义集中的内容,则会插入一个空字符串。请注意,在插入所有重复值之前,都会丢弃所有重复值,因此只插入每个允许值的一个实例。

      希望这能解决问题。

      请注意,Winbobob 的回答是不正确的,并且包含有缺陷的示例,因为在插入多个值时,值必须是字符串,用逗号分隔。他所有的插入实际上只是插入了一个值(最后两个不在定义的集合中)

      【讨论】:

        【解决方案6】:

        ENUM --> 只选择一个可用的值来插入。

        (no_null, no_any_duplicate)


        SET --> 选择任意组合或单个值,如集合并将它们插入。

        (null, individual_values, all_the_available_values_together)

        【讨论】:

          【解决方案7】:

          我补充了迄今为止答案中已经提到的几点,因为我正在添加一个关于差异的附加点 -

          MySQL 在内部将 ENUM 字符串值存储为值 1 到 n 的十进制整数,用于枚举中具有 n 个成员的列。

          MySQL 将 SET 字符串值表示为一个位图,每个值使用一位,因此这些值在内部存储为 1、2、4、8、..... 最多 65,535 个,最多 64 个成员。

          这点演示如下-

          枚举示例 -

          我创建表table1,列col1 的数据类型为ENUM('a','b','c','d','e','f','g','h','i','j'),表结构如下-

          | table1 | CREATE TABLE `table1` (
            `id` int unsigned NOT NULL AUTO_INCREMENT,
            `col1` enum('a','b','c','d','e','f','g','h','i','j') DEFAULT NULL,
            PRIMARY KEY (`id`)
          ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci |
          

          col1 内部存储如下 -

          +----+---------+---------------+
          | id | element | decimal_value |
          +----+---------+---------------+
          |  1 | a       |             1 |
          |  2 | b       |             2 |
          |  3 | c       |             3 |
          |  4 | d       |             4 |
          |  5 | e       |             5 |
          |  6 | f       |             6 |
          |  7 | g       |             7 |
          |  8 | h       |             8 |
          |  9 | i       |             9 |
          | 10 | j       |            10 |
          +----+---------+---------------+
          

          现在,假设我们要将值 - 'e' 插入到 col1

          'e' 的索引为 5

          因此要将'e' 输入col1,我们使用以下查询-

          INSERT INTO table1  VALUES (1, 5);
          

          然后我们检查table1中存在的值-

          SELECT * FROM table1;
          +----+------+
          | id | col1 |
          +----+------+
          |  1 | e    |
          +----+------+
          

          我们看到,在第一行中,col1 的值为 'e'

          再次,假设我们要将值 - 'i' 插入到 col1

          'i' 的索引为 9

          因此要将'i' 输入col1,我们使用以下查询-

          INSERT INTO table1  VALUES (2, 9);
          

          然后我们检查table1中存在的值-

          SELECT * FROM table1;
          +----+------+
          | id | col1 |
          +----+------+
          |  1 | e    |
          |  2 | i    |
          +----+------+
          

          我们看到,在第二行中,col1 的值为 'i'

          再次,假设我们要将值 - 'a' 插入到 col1

          'a' 的索引为 1

          因此要将'a' 输入col1,我们使用以下查询-

          INSERT INTO table1  VALUES (3, 1);
          

          然后我们检查table1中存在的值-

          SELECT * FROM table1;
          +----+------+
          | id | col1 |
          +----+------+
          |  1 | e    |
          |  2 | i    |
          |  3 | a    |
          +----+------+
          

          我们看到在第三行我们将col1 的值设为'a'


          SET 示例 -

          我创建表table1,列col1,数据类型为SET('a','b','c','d','e','f','g','h','i','j'),表结构如下-

          | table1 | CREATE TABLE `table1` (
            `id` int unsigned NOT NULL AUTO_INCREMENT,
            `col1` set('a','b','c','d','e','f','g','h','i','j') DEFAULT NULL,
            PRIMARY KEY (`id`)
          ) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci |
          

          col1 内部存储如下 -

          +----+---------+----------------+---------------+
          | id | element | binary_value   | decimal_value |
          +----+---------+----------------+---------------+
          |  1 | a       | 0000 0000 0001 |             1 |
          |  2 | b       | 0000 0000 0010 |             2 |
          |  3 | c       | 0000 0000 0100 |             4 |
          |  4 | d       | 0000 0000 1000 |             8 |
          |  5 | e       | 0000 0001 0000 |            16 |
          |  6 | f       | 0000 0010 0000 |            32 |
          |  7 | g       | 0000 0100 0000 |            64 |
          |  8 | h       | 0000 1000 0000 |           128 |
          |  9 | i       | 0001 0000 0000 |           256 |
          | 10 | j       | 0010 0000 0000 |           512 |
          +----+---------+----------------+---------------+
          

          现在,假设我们要将值 - 'e,f,i' 插入到 col1

          那么'e,f,i'的binary_value是通过将'e''f''i'的binary_value相加得到0001 0011 0000,对应的decimal_value就是304如下图-

          +----+---------+----------------+---------------+
          | id | element | binary_value   | decimal_value |
          +----+---------+----------------+---------------+
          |  5 | e       | 0000 0001 0000 |            16 |
          |  6 | f       | 0000 0010 0000 |            32 |
          |  9 | i       | 0001 0000 0000 |           256 |
          +----+---------+----------------+---------------+
          |    | e,f,i   | 0001 0011 0000 |           304 |
          +----+---------+----------------+---------------+
          

          因此要将'e,f,i' 输入col1,我们使用以下查询-

          INSERT INTO table1  VALUES (1, 304);
          

          然后我们检查table1中存在的值-

          SELECT * FROM table1;
          +----+-------+
          | id | col1  |
          +----+-------+
          |  1 | e,f,i |
          +----+-------+
          

          我们看到,在第一行中,col1 的值为 'e,f,i'

          再次,假设我们要将值 - 'a,j' 插入到 col1

          然后'a,j'的binary_value是'a''j'的binary_values相加,即0010 0000 0001,对应的decimal_value为513,如下图-

          +----+---------+----------------+---------------+
          | id | element | binary_value   | decimal_value |
          +----+---------+----------------+---------------+
          |  1 | a       | 0000 0000 0001 |             1 |
          | 10 | j       | 0010 0000 0000 |           512 |
          +----+---------+----------------+---------------+
          |    | a,j     | 0010 0000 0001 |           513 |
          +----+---------+----------------+---------------+
          

          因此要将'a,j' 输入col1,我们使用以下查询-

          INSERT INTO table1  VALUES (2, 513);
          

          然后我们检查table1中存在的值-

          SELECT * FROM table1;
          +----+-------+
          | id | col1  |
          +----+-------+
          |  1 | e,f,i |
          |  2 | a,j   |
          +----+-------+
          

          我们看到,在第二行中,col1 的值为 'a,j'

          再次,假设我们要将值 - 'b,d,h,i' 插入到 col1

          然后'b,d,h,i'的binary_value是通过将'b''d''h''i'的binary_value相加得到的,即0001 1000 1010,对应的decimal_value为394,如下图-

          +----+---------+----------------+---------------+
          | id | element | binary_value   | decimal_value |
          +----+---------+----------------+---------------+
          |  2 | b       | 0000 0000 0010 |             2 |
          |  4 | d       | 0000 0000 1000 |             8 |
          |  8 | h       | 0000 1000 0000 |           128 |
          |  9 | i       | 0001 0000 0000 |           256 |
          +----+---------+----------------+---------------+
          |    | b,d,h,i | 0001 1000 1010 |           394 |
          +----+---------+----------------+---------------+
          

          因此要将'b,d,h,i' 输入col1,我们使用以下查询-

          INSERT INTO table1  VALUES (3, 394);
          

          然后我们检查table1中存在的值-

          SELECT * FROM table1;
          +----+---------+
          | id | col1    |
          +----+---------+
          |  1 | e,f,i   |
          |  2 | a,j     |
          |  3 | b,d,h,i |
          +----+---------+
          

          我们看到在第三行我们将col1 的值设为'b,d,h,i'

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2015-10-14
            • 2011-04-09
            • 1970-01-01
            • 2012-02-18
            • 1970-01-01
            • 2019-06-08
            • 1970-01-01
            • 2020-08-10
            相关资源
            最近更新 更多