MySQL - Выбрать в столбце varchar с 0 (ноль), поскольку критерии возвращают все строки? - PullRequest
1 голос
/ 13 марта 2020

Извините заранее - это кажется очень глупым вопросом. Но ...

Если я запускаю запрос select для столбца varchar(), но использую ноль для значения столбца в предложении where - почему он возвращает все строки?

Например:

CREATE TABLE test (
  id INT,
  person varchar(50)
);
INSERT INTO test (id, person) VALUES (1, "Alice");
INSERT INTO test (id, person) VALUES (2, "Bob");

SELECT * FROM test where person = 0;

Я ожидаю, что это либо вернет ошибку, либо пустой набор результатов. Вместо этого он возвращает все строки?!?!

Почему это так?

Ответы [ 2 ]

3 голосов
/ 13 марта 2020

Выражение:

person = 0

содержит 2 операнда разных типов данных. В этом случае MySql выполняет неявное преобразование, как объяснено в 12.2 Преобразование типов в оценке выражений Таким образом, значение типа 'Bob' неявно преобразуется в значение с плавающей запятой, и это значение равно 0. Существуют случаи, когда строка будет преобразована в значение, отличное от 0, например, когда строка начинается с части цифры c, а затем эта часть нумерации c является ее преобразованным значением, поэтому:

  • '12abc6' будет преобразован в 12, а
  • '5.6xyz0' будет преобразован в 5.6

исключение в этом Правило - это строка типа '2e3', которая интерпретируется как 2 * 10^3 (нотация scientifi c), поэтому она преобразуется в 2000. В вашем коде все имена конвертируются в 0, поэтому условие становится:

0 = 0 

, что всегда true.

2 голосов
/ 13 марта 2020

То, что вы видите, называется неявное преобразование . Поскольку вы просите MySQL сравнить строку с целым числом, она переводит строку в число, а затем сравнивает результат.

И получается, что в MySQL любая строка, которая не начинается с ди git преобразуется в 0. Это соответствует вашему предикату where, отсюда и результаты, которые вы видите.

Общее правило: не полагайтесь на неявное приведение; при передаче литеральных значений в ваших запросах, используйте правильный тип данных (здесь 0 должно быть '0'). При сравнении столбцов таблицы выполняйте приведение по мере необходимости.

Вот небольшая демонстрация 1014 * сравнений int / string.

select 
    'foo' = '0',  -- false (as expected)
    'foo' = 0,    -- true!
    '0foo' = 0    -- true ("0foo" starts with "0")
'foo' = '0' | 'foo' = 0 | '0foo' = 0
----------: | --------: | ---------:
          0 |         1 |          1
...