Выберите по столбцу varchar с частью IN () в условии, а значение int возвращает все строки - PullRequest
1 голос
/ 14 января 2010

Может кто-нибудь объяснить мне, почему с этим запросом:

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');

Я также получаю ту же ошибку, что и Роланд Буман:

Truncated incorrect DOUBLE value: 'willa-lentza'

Ответы [ 4 ]

4 голосов
/ 14 января 2010

Вы никогда не должны смешивать цитируемые и значения без кавычек в списке IN, потому что правила сравнения для указанных значений (например, строки) и значения без кавычек (например, цифры) отличаются. Смешивание типов поэтому может привести к противоречивым Результаты.

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

1 голос
/ 14 января 2010

Интересно ... я получил это.

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)

но я все еще не могу объяснить поведение ОП

0 голосов
/ 14 января 2010

Я не могу воспроизвести это поведение, но кажется, что ваше varchars преобразуется в DOUBLEs, а не наоборот.

В этом случае запрос превращается в такой:

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

0 голосов
/ 14 января 2010

Мое краткое тестирование не подтверждает это поведение.

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

Не любая строка должна соответствовать целому числу. Вы уверены, что больше ничего не меняли?

...