1

我今天尝试select sum从 ENUM 字段中发现一些奇怪的东西。它在值上加了 1!我使用的示例表如下所示:

x     y
_______
3  |  2
0  |  1

xy都是_ENUM ('0','1','2','3')

我的查询如下:

select sum(x), sum(y), sum(x+y) from myfield

结果是:

5    5   10

这很奇怪。这是否意味着这种行为是一致的?我可以使用类似的东西:

select sum(x - 1), sum(y - 1), sum((x-1)+(y-1)) from myfield

哪一个会产生正确的结果,或者这种行为仅对我的数据库服务器特别有影响?

谢谢。

编辑: 对于那些想知道我为什么使用 ENUM 的人,这是因为我使用的实际字段包含无法放入tinyint.

4

2 回答 2

3

由于ENUM字段实际上只是一个INT UNSIGNED,因此如果您对 s 使用整数值,它将无法按预期工作ENUM。例如, your ENUMof '0', 在内部存储为 numeric 1,而 your '1', 存储为 numeric 2。令人惊讶的是,空字符串''在内部存储为0. 这是一个无法按预期工作的示例:

mysql> CREATE TABLE enumtest (
    -> id int unsigned NOT NULL AUTO_INCREMENT PRIMARY KEY,
    -> a ENUM ('0','1','2','3') NOT NULL DEFAULT '0',
    -> i int unsigned NOT NULL DEFAULT 0
    -> );
Query OK, 0 rows affected (0.00 sec)

mysql> INSERT INTO enumtest SET a = 0, i=0;
Query OK, 1 row affected, 1 warning (0.01 sec)

mysql> SHOW WARNINGS;
+---------+------+----------------------------------------+
| Level   | Code | Message                                |
+---------+------+----------------------------------------+
| Warning | 1265 | Data truncated for column 'a' at row 1 |
+---------+------+----------------------------------------+
1 row in set (0.00 sec)

mysql> INSERT INTO enumtest SET a = '0', i=0;
Query OK, 1 row affected (0.01 sec)

mysql> INSERT INTO enumtest SET a = 1, i=1;
Query OK, 1 row affected (0.01 sec)

mysql> INSERT INTO enumtest SET a = '1', i=1;
Query OK, 1 row affected (0.00 sec)

mysql> SELECT a,0+a,i FROM enumtest;                   
+---+-----+---+
| a | 0+a | i |
+---+-----+---+
|   |   0 | 0 |
| 0 |   1 | 0 |
| 0 |   1 | 1 |
| 1 |   2 | 1 |
+---+-----+---+
4 rows in set (0.00 sec)

mysql> SELECT SUM(a),SUM(0+a), SUM(i) FROM enumtest;    
+--------+----------+--------+
| SUM(a) | SUM(0+a) | SUM(i) |
+--------+----------+--------+
|      4 |        4 |      2 |
+--------+----------+--------+
1 row in set (0.00 sec)

该子句将其0+a强制ENUM转换为其基础UNSIGNED值。这相当于CAST(a AS UNSIGNED)

于 2013-06-27T21:31:48.417 回答
2

这是因为SUM()在枚举列上做的事情并没有像你想象的那样做。为枚举列类型存储的数据是枚举的索引,该索引从 1 开始,mysql 将使用这个索引SUM()

您的表格在显示时如下所示:

x     y
_______
3  |  2
0  |  1

这显示了您的枚举值 - 您恰好也将枚举值定义为数字。您可以将它们定义为 egENUM ('blue','red','green','yellow') 它看起来像:

x         y
_______________
yellow  |  green
blue    |  red

但是,这仅用于展示。该表的行中实际存储的是枚举中的索引。

列规范中列出的元素分配有索引号,从 1 开始。

因此,这些索引从 1 开始。SUM() 和其他聚合函数用于 ENUM 列的正是这些基础数据。没有对枚举值的隐式转换,您也将其定义为数字。

即存储的数据是这些索引:

x     y
_______
4  |  3
1  |  2

虽然它对 SUM 枚举没有真正意义,但 mysql 在使用时会聚合这些索引SUM()

文档是必读的。

于 2013-06-27T21:32:00.337 回答