在varchar列中选择条件为IN()的部分,int值返回所有行

时间:2010-01-14 14:31:29

标签: mysql varchar

有人可以用该查询解释我的原因:

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 个答案:

答案 0 :(得分:4)

  

你永远不应该混合引用和   IN列表中的未加引号的值,因为   引用值的比较规则   (例如字符串)和不带引号的值   (如数字)不同。混合类型   因此可能导致不一致   结果

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

答案 1 :(得分: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在列表中,mysql认为其余的og在列表中,左手参数'a'应该都是数字。铸造'a'将导致0,所以这将被视为{{1 }}

但我还是无法解释OP的行为

答案 2 :(得分:0)

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

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

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

答案 3 :(得分:0)

我无法重现此行为,但似乎您的varchars会被投放到DOUBLEs而不是相反。

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

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

对于所有非数字标签始终为true。

您可以在此声明中运行EXPLAIN EXTENDED SELECT ...并在此处发布警告吗?

要确认此行为,您可以添加其他数字标记:

INSERT
INTO    tags
VALUES  (6, '1000')

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

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