2010-01-14 1 views
1

Может кто-нибудь объяснить мне, почему с этим запросом:Выбор по VARCHAR колонки с IN() часть в состоянии и INT значение возвращает все строки

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

это вернуть мне все строки из tags таблицы, но когда я ставлю 2016 в кавычки он работает хорошо?

tag column varchar type.

ОБРАЗЦА СРЕДЫ

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 Боуман:

Truncated incorrect DOUBLE value: 'willa-lentza' 
+0

Is представляет собой автономный запрос или часть хранимой процедуры? – Quassnoi

+0

Автономный через Mysql Query Browser – hsz

+0

На моем '5.1.35' это возвращает правильные результаты:' 2' записывает как с кавычками, так и без них. Какую версию вы используете? – Quassnoi

ответ

4

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

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

0

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

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

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

+0

Я на 100% уверен. См. Мое редактирование (пример env). – hsz

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' 

EDIT: на самом деле я думаю, что могу exaplain этот. (потому что 0 находится в списке, mysql думает, что остальное находится в списке, а также левый аргумент «a» должен быть числом. Литье «a» приведет к 0, так что это будет внутренне рассматриваться как 0 in (0, 0)

, но я до сих пор не могу объяснить поведение OP

+0

Если целочисленное значение равно 0, утверждение представляется истинным. Если это любое другое целое число, оно кажется ложным. – Matchu

+0

См. Мои данные в первом сообщении. – hsz

0

Я не могу воспроизвести это поведение, но мне кажется, что ваш 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

'Усеченное неправильное ДВОЙНОЕ значение: 'willa-lentza'' – hsz

+0

' @ hsz': Это он. 'EXPLAIN EXTENDED' должен выдать другое предупреждение с данными плана и кодом' 1003'. Не могли бы вы найти и опубликовать его? – Quassnoi

+0

Ah, ok - вот вы: 'select tags.id AS id, tags.tag AS тег из тегов где (tags.tag in (_utf8'willa-lentza ', 2016))' Ничто не более того (это обозначен как «1003»). – hsz