Подтвердить что ты не робот

Почему MySQL возвращает строки, которые, по-видимому, не соответствуют предложению WHERE?

предположим, что пользовательский ввод

mysite.com/profile?identity=1
mysite.com/profile?identity=dinodsja
mysite.com/profile?identity=1a

получение значения

$identity = $_GET['identity']; // identity can be user_id or user_name

и у меня есть простой запрос select:

SELECT * FROM lb_users WHERE (user_id = 'dinodsja' OR user_name = 'dinodsja') AND user_status = 1

и он отлично работает. но проблема заключается в следующем:

SELECT * FROM lb_users WHERE (user_id = '1a' OR user_name = '1a') AND user_status = 1

когда я выполняю этот запрос, он также возвращает результат без выполнения условия.

Структура таблицы:

user_id     bigint(25)
user_name   varchar(50)     utf8_general_ci

enter image description here

**

-> Is this a MySQL Bug ? 
-> How can we avoid this ? 
-> What will be the query ?

**

4b9b3361

Ответ 1

Я давно помню, что у меня была аналогичная проблема.

Сначала немного фона: это не ошибка. Это на самом деле особенность. Хорошо, это может привести к такому неожиданному поведению, но MySQL, таким образом, очень толерантен w.r.t. пользовательские входы, соответствующие запросы выбора:

mysql> SELECT 'a' = 'a ';
        -> 1
mysql> SELECT 'A' = 'a';
        -> 1

Следовательно, при неявном преобразовании типов результат, например, '1a' в INTEGER равен 1, но также:

mysql> SELECT 0 = 'x6';
        -> 1
mysql> SELECT 1 = ' 1';
        -> 1
mysql> SELECT 1 = ' 1a';
        -> 1

Эта функция также реализована на других нестатически типизированных языках. PHP, например, вызывает этот тип жонглирования. См. Правила преобразования PHP String и этот пример из документации:

<?php
  $foo = "0";                     // $foo is string (ASCII 48)
  $foo += 2;                      // $foo is now an integer (2)
  $foo = $foo + 1.3;              // $foo is now a float (3.3)
  $foo = 5 + "10 Little Piggies"; // $foo is integer (15)
  $foo = 5 + "10 Small Pigs";     // $foo is integer (15)
?>

Смотрите JavaScript:

<script>
  document.write(parseInt("40 years") + "<br>");
</script>

=> 40

Тем не менее, решение вашей проблемы довольно просто: просто введите целое число в char и выполните сравнение:

mysql> SELECT * FROM lb_users WHERE (CAST(user_id AS CHAR) = '1' OR user_name = '1')
        -> 1
mysql> SELECT * FROM lb_users WHERE (CAST(user_id AS CHAR) = '1a' OR user_name = '1a')
        -> 0
mysql> SELECT * FROM lb_users WHERE (CAST(user_id AS CHAR) = 'dinodsja' OR user_name = 'dinodsja')
        -> 1

Я сделал скрипку для всех, чтобы попробовать: http://sqlfiddle.com/#!2/c2835/14/0

Надеюсь, что это поможет,

-Hannes

Ответ 2

Причина этого в том, что тип данных столбца user_ID является целым числом.

MySQL бесшумно помещает в значение значение NON-Number (и все, что следует за ним), поэтому 1a равно 1, так как a будет удаляться в значение.

Ответ 3

Согласно вашему предыдущему сообщению

его пользовательский ввод для профиля. пользователь может указать user_id или user_name. поэтому вход действителен. но нет данных. - DBK 30 марта в 6:42

Я бы рекомендовал тестирование, чтобы увидеть, является ли его целое число и только поиск идентификатора пользователя, если он является целым числом. Это действительно более обходное решение для mySQL, не обрабатывающего сравнение STRING-INT, но оно должно работать.

declare @InputVar varchar(10)
set @InputVar = '1a'

SELECT *  
FROM lb_users
WHERE  
  (case when isnumeric(@InputVar) = 1 then 
    case when (user_id = @InputVar OR user_name = @InputVar) then 1 else 0 end
  else  
    case when user_name = @InputVar then 1 else 0 end
  end =1 )
And 
  user_status = 1

Ответ 4

При работе со строками я бы использовал "LIKE" вместо "=", чтобы избежать безумства преобразования молчащего типа. LIKE используется для работы со строками, поэтому почему бы не использовать его.

Ответ 5

SELECT * FROM lb_users WHERE (user_id = '1a' OR user_name = '1a') AND user_status = 1

вы получите 1 результат, если вы измените '1a' на 1a, вы получите следующее:

# 1064 - У вас есть ошибка в синтаксисе SQL; проверьте руководство, соответствующее версии вашего сервера MySQL, для правильного синтаксиса для использования рядом с "1a LIMIT 0, 30" в строке 1

Это не ошибка, посмотрите http://dev.mysql.com/doc/refman/5.0/en/where-optimizations.html

надеюсь, что это поможет

Ответ 6

Я думаю, что вы не можете дублировать первичный ключ и идентификатор, я тестирую его, и я придумываю текущие данные... вы задали user_id своими атрибутами, например:

user_id bigint(50) auto_increment primary key

это не ошибка mysql.