web-dev-qa-db-ja.com

MySQLでSQLの大文字と小文字を区別する文字列比較を行うにはどうすればよいですか?

大文字と小文字が混在する5文字を返す関数があります。この文字列に対してクエリを実行すると、大文字と小文字に関係なく値が返されます。

MySQLの文字列クエリで大文字と小文字を区別するにはどうすればよいですか?

245
StevenB

http://dev.mysql.com/doc/refman/5.0/en/case-sensitivity.html

デフォルトの文字セットと照合順序はlatin1とlatin1_swedish_ciなので、非バイナリ文字列の比較ではデフォルトで大文字と小文字が区別されません。つまり、col_name LIKE 'a%'で検索した場合、Aまたはaで始まるすべての列値が得られます。この検索で​​大文字と小文字が区別されるようにするには、オペランドの1つに大文字と小文字が区別されるかバイナリ照合があるようにします。たとえば、両方ともlatin1文字セットを持つ列と文字列を比較する場合は、COLLATE演算子を使用して、いずれかのオペランドにlatin1_general_csまたはlatin1_bin照合順序を設定できます。

col_name COLLATE latin1_general_cs LIKE 'a%'
col_name LIKE 'a%' COLLATE latin1_general_cs
col_name COLLATE latin1_bin LIKE 'a%'
col_name LIKE 'a%' COLLATE latin1_bin

列を常に大文字と小文字を区別して扱うようにする場合は、大文字と小文字を区別するバイナリ照合順序で宣言します。

136
drudge

幸い、大文字と小文字を区別するクエリを実行する必要がある場合は、簡単に実行できます。

SELECT *  FROM `table` WHERE BINARY `column` = 'value'
643
Craig White

=演算子を使用する代わりに、LIKEまたはLIKE BINARYを使用することをお勧めします。

// this returns 1 (true)
select 'A' like 'a'

// this returns 0 (false)
select 'A' like binary 'a'


select * from user where username like binary 'a'

それはその状態に 'A'ではなく 'a'を取ります

35
insoftservice

回答がCraig Whiteに投稿されました、パフォーマンスに大きなペナルティがあります

SELECT *  FROM `table` WHERE BINARY `column` = 'value'

それはインデックスを使わないからです。そのため、ここで述べるようにテーブルの照合順序を変更する必要があります https://dev.mysql.com/doc/refman/5.7/en/case-sensitivity.html

OR

最も簡単な解決策は、値のバイナリを使用する必要があります。

SELECT *  FROM `table` WHERE `column` = BINARY 'value'

例えば。

mysql> EXPLAIN SELECT * FROM temp1 WHERE BINARY col1 = "ABC" AND col2 = "DEF" ;
+----+-------------+--------+------+---------------+------+---------+------+--------+-------------+
| id | select_type | table  | type | possible_keys | key  | key_len | ref  | rows   | Extra       |
+----+-------------+--------+------+---------------+------+---------+------+--------+-------------+
|  1 | SIMPLE      | temp1  | ALL  | NULL          | NULL | NULL    | NULL | 190543 | Using where |
+----+-------------+--------+------+---------------+------+---------+------+--------+-------------+

VS

mysql> EXPLAIN SELECT * FROM temp1 WHERE col1 = BINARY "ABC" AND col2 = "DEF" ;
+----+-------------+-------+-------+---------------+---------------+---------+------+------+------------------------------------+
| id | select_type | table | type  | possible_keys | key           | key_len | ref  | rows | Extra                              |
+----+-------------+-------+-------+---------------+---------------+---------+------+------+------------------------------------+
|  1 | SIMPLE      | temp1 | range | col1_2e9e898e | col1_2e9e898e | 93      | NULL |    2 | Using index condition; Using where |
+----+-------------+-------+-------+---------------+---------------+---------+------+------+------------------------------------+
enter code here

1行セット(0.00秒)

32
Nitesh

BINARYを使用する前にインデックスを利用するには、大きなテーブルがある場合はこのようにすることができます。

SELECT
   *
FROM
   (SELECT * FROM `table` WHERE `column` = 'value') as firstresult
WHERE
   BINARY `column` = 'value'

サブクエリの結果、大文字と小文字が区別されない非常に小さいサブセットが生成され、その中から大文字と小文字を区別する唯一の一致が選択されます。

13
Eric

以下はMySQLのバージョンが5.5以上の場合です。

/etc/mysql/my.cnfに追加します。

  [mysqld]
  ...
  character-set-server=utf8
  collation-server=utf8_bin
  ...

私が試した他のすべての照合は大文字と小文字を区別しないように見え、 "utf8_bin"のみが機能しました。

この後にmysqlを再起動することを忘れないでください。

   Sudo service mysql restart

http://dev.mysql.com/doc/refman/5.0/en/case-sensitivity.html によると、 "latin1_bin"もあります。 。

"utf8_general_cs"はmysqlの起動には受け入れられませんでした。 (私は "_cs"を "大文字と小文字を区別する"と読みました - ???)。

7
fritzthecat

あなたはこのように大文字と小文字を区別するためにBINARYを使うことができます

select * from tb_app where BINARY Android_package='com.Mtime';

残念ながら、このSQLではインデックスを使用できません。そのインデックスに依存するクエリでパフォーマンスが低下する可能性があります。

mysql> explain select * from tb_app where BINARY Android_package='com.Mtime';
+----+-------------+--------+------------+------+---------------+------+---------+------+---------+----------+-------------+
| id | select_type | table  | partitions | type | possible_keys | key  | key_len | ref  | rows    | filtered | Extra       |
+----+-------------+--------+------------+------+---------------+------+---------+------+---------+----------+-------------+
|  1 | SIMPLE      | tb_app | NULL       | ALL  | NULL          | NULL | NULL    | NULL | 1590351 |   100.00 | Using where |
+----+-------------+--------+------------+------+---------------+------+---------+------+---------+----------+-------------+

幸い、私はこの問題を解決するためのいくつかのトリックを持っています

mysql> explain select * from tb_app where Android_package='com.Mtime' and BINARY Android_package='com.Mtime';
+----+-------------+--------+------------+------+---------------------------+---------------------------+---------+-------+------+----------+-----------------------+
| id | select_type | table  | partitions | type | possible_keys             | key                       | key_len | ref   | rows | filtered | Extra                 |
+----+-------------+--------+------------+------+---------------------------+---------------------------+---------+-------+------+----------+-----------------------+
|  1 | SIMPLE      | tb_app | NULL       | ref  | idx_Android_pkg           | idx_Android_pkg           | 771     | const |    1 |   100.00 | Using index condition |
+----+-------------+--------+------------+------+---------------------------+---------------------------+---------+-------+------+----------+-----------------------+  
5
xiezefan

DBレベルでは何も変更する必要はありません。動作するのはSQLクエリで変更するだけです。

例 -

"SELECT * FROM <TABLE> where userId = '" + iv_userId + "' AND password = BINARY '" + iv_password + "'";

バイナリキーワードでは大文字と小文字が区別されます。

1
Pappu Mehta

優秀な!

私はあなたと共有します、パスワードを比較する関数からのコード:

SET pSignal =
(SELECT DECODE(r.usignal,'YOURSTRINGKEY') FROM rsw_uds r WHERE r.uname =
in_usdname AND r.uvige = 1);

SET pSuccess =(SELECT in_usdsignal LIKE BINARY pSignal);

IF pSuccess = 1 THEN
      /*Your code if match*/
ELSE
      /*Your code if don't match*/

END IF;
1
Victor Enrique

問合せ対象の列の照合順序を変更せずに大文字と小文字を区別する文字列比較を実行する最も正確な方法は、列の比較対象の値に対して文字セットと照合順序を明示的に指定することです。

select * from `table` where `column` = convert('value' using utf8mb4) collate utf8mb4_bin;

なぜbinaryを使わないのですか?

binary演算子は、エンコードされた文字列の実際のバイト数を比較するため、使用することはお勧めできません。異なる文字セットを使用してエンコードされた2つの文字列の実際のバイト数を比較すると、同じと見なすべき2つの文字列は等しくない可能性があります。たとえば、latin1文字セットを使用する列があり、サーバー/セッションの文字セットがutf8mb4である場合、 'café'などのアクセントを含む文字列とその列を比較すると、その同じ文字列を含む行とは一致しません。 !これは、latin1ではéがバイト0xE9としてエンコードされていますが、utf8では2バイト、0xC3A9であるためです。

なぜconvertcollateを使うのですか?

照合順序は文字セットと一致する必要があります。したがって、サーバーまたはセッションがlatin1文字セットを使用するように設定されている場合はcollate latin1_binを使用する必要がありますが、文字セットがutf8mb4である場合はcollate utf8mb4_binを使用する必要があります。したがって、最も堅牢な解決策は、常に値を最も柔軟な文字セットに変換し、その文字セットにバイナリ照合順序を使用することです。

列ではなく値にconvertおよびcollateを適用するのはなぜですか。

比較を行う前に列に変換関数を適用すると、列にインデックスが存在する場合、クエリエンジンはインデックスを使用できなくなり、クエリが大幅に遅くなる可能性があります。そのため、可能な場合は代わりに値を変換することをお勧めします。 2つの文字列値の間で比較が実行され、そのうちの1つに明示的に指定された照合順序がある場合、クエリエンジンは適用される値に関係なく明示的な照合順序を使用します。

アクセント感度

MySqlは_ci照合を使用する列に対して大文字と小文字を区別しないだけでなくアクセントを区別しないことに注意することが重要です。これは'é' = 'e'という意味です。バイナリ照合(またはbinary演算子)を使用すると、文字列比較では大文字と小文字が区別されるだけでなく、アクセントも区別されます。

utf8mb4とは何ですか?

MySqlのutf8文字セットは、4バイト文字(????のような文字列のエンコードに重要)をサポートしていないため、 最近のバージョンでは非推奨 となっているutf8mb3のエイリアスです。 MySqlで TF8文字エンコード を使用したい場合は、utf8mb4文字セットを使用してください。

1
Paul Wheeler

mysqlはデフォルトでは大文字と小文字を区別しません。言語の照合順序をlatin1_general_csに変更してみてください

0
ohmusama