22

ユーザー入力を想定する

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 * 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

ここに画像の説明を入力

**

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

**

4

6 に答える 6

32

その理由は、列のデータ型user_IDが整数であるためです。

MySQLは値の末尾 の NON-Number (および 内に続くもの) を黙って削除します。1a1a

于 2013-03-30T06:35:18.397 に答える
24

私はずっと前に同様の問題を抱えていたことを覚えています。

最初の背景: これはバグではありません。それは実際には機能です。わかりました、それはそのような予期しない動作につながる可能性があるものですが、MySQL はユーザー入力、それぞれの選択クエリに対して非常に寛容です:

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

したがって、暗黙的な型変換を使用すると、たとえば'1a'in INTEGER の結果は 1 になりますが、次のこともできます。

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

この機能は、静的に型付けされていない他の言語にも実装されています。たとえば、PHP はこの型を jugglingと呼んでいます。ドキュメントのPHP 文字列変換規則とこの例を参照してください。

<?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

それが役立つことを願って、

-ハンネス

于 2013-04-03T05:24:14.223 に答える
0

文字列を扱うときは、「=」の代わりに「LIKE」を使用して、この暗黙の型変換の狂気を回避します。LIKE は文字列で動作するように作られているので、使用しないでください。

于 2013-04-05T09:35:58.867 に答える
0

主キーと ID を複製することはできないと思います。それをテストすると、実行中のデータが表示されます。次のような属性で user_id を設定しましたか。

user_id bigint(50) auto_increment primary key

これは mysql エラーではありません。

于 2013-04-10T04:58:32.440 に答える
0

前回のメッセージによると

プロファイルのユーザー入力です。user は user_id または user_name を指定できます。したがって、入力は有効です。しかし、データはありません。– DBK 3 月 30 日 6:42

整数かどうかをテストして、整数の場合にのみユーザー ID を検索することをお勧めします。これは実際には、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
于 2013-04-04T19:36:24.540 に答える