1

有人可以用这个查询解释我为什么:

SELECT * FROM `tags` WHERE (tag IN ('willa-lentza', 2016))

它从表中返回所有行tags,但是当我放入2016引号时效果很好?

tag列是varchar类型。

示例环境

CREATE TABLE  `tags` (
  `id` int(10) unsigned NOT NULL auto_increment,
  `tag` varchar(255) NOT NULL,
  PRIMARY KEY  (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=6 DEFAULT CHARSET=utf8

INSERT INTO `tags` (`id`, `tag`) VALUES
  (1, '2016'),
  (2, 'plum'),
  (3, 'banana'),
  (4, 'apple'),
  (5, 'willa-lentza');

我也得到与 Roland Bouman 相同的错误:

Truncated incorrect DOUBLE value: 'willa-lentza'
4

4 回答 4

4

切勿在 IN 列表中混用带引号和不带引号的值,因为带引号的值(例如字符串)和不带引号的值(例如数字)的比较规则不同。因此,混合类型可能会导致结果不一致。

http://dev.mysql.com/doc/refman/5.0/en/comparison-operators.html#function_in

于 2010-01-14T14:46:40.933 回答
1

有趣……我明白了。

mysql> select 'a' in (0, 'b');
+-----------------+
| 'a' in (0, 'b') |
+-----------------+
|               1 |
+-----------------+
1 row in set, 1 warning (0.00 sec)

Warning (Code 1292): Truncated incorrect DOUBLE value: 'a'

编辑:实际上我想我可以解释这个。(因为 0 在 in 列表中,mysql 认为 in 列表中的其余部分以及左侧参数 'a' 都应该是数字。强制转换 'a' 将导致 0,所以这将被视为0 in (0, 0)

但我仍然无法解释 OP 的行为

于 2010-01-14T14:41:24.893 回答
0

我的简短测试并未证实这种行为。

SELECT 'test' IN ('other-string', 2016) /* returns 0 */

不仅仅是任何字符串都应该能够匹配整数。你确定你没有改变任何东西吗?

于 2010-01-14T14:39:11.277 回答
0

我无法重现这种行为,但似乎你varchars被铸造成 aDOUBLEs而不是相反。

在这种情况下,查询变为:

SELECT  *
FROM    tags
WHERE   CAST(tag AS DOUBLE) /* =0 for non-numeric tags */ IN (CAST('willa-lentza AS DOUBLE) /* = 0 */, 2016)

对于所有非数字标签,这始终是正确的。

您能否执行EXPLAIN EXTENDED SELECT ...此声明并在此处发布警告?

要确认此行为,您可以添加另一个数字标签:

INSERT
INTO    tags
VALUES  (6, '1000')

两个查询都不应返回此标记。

为避免这种情况,只需始终将常量括在单引号中,以便将它们解析为CHARs

于 2010-01-14T14:51:07.227 回答