2016-09-13 3 views
0

The **compare-on-binary way** is **NOT semantically-correct** MySQLの厳密な文字列の比較は、意味的に正しい方法ですか?例えば

、あなたは異なる符号化文字列と厳格-文字列の比較をしたい、比較・オン・バイナリの方法のミスが出てきます。次のテストケースは、理由を示しています。この場合

は、私は、文字列'北京111'にフィールド城市に(taillingスペース付き)、文字列'北京 'を交換したいのですが、'北京'そのまま文字列を維持するので、私は次のSQLを書き留め:

SELECT CASE WHEN BINARY `城市` = BINARY '北京 ' THEN '北京111' ELSE `城市` END 
FROM `中文测试表1` 
GROUP BY BINARY CASE WHEN BINARY `城市` = BINARY '北京 ' THEN '北京111' ELSE `城市` END 

基本となるテーブル定義とデータ(セッションエンコーディングが 'utf8mb4' にsettedさ):

CREATE TABLE `中文测试表1` (
    `城市` varchar(50) CHARACTER SET gbk DEFAULT NULL, 
    `销量` int(11) DEFAULT NULL 
) ENGINE=InnoDB; 

INSERT INTO `中文测试表1` VALUES ('杭州', '111'); 
INSERT INTO `中文测试表1` VALUES ('北京', '345'); 
INSERT INTO `中文测试表1` VALUES ('北京 ', '123'); 

そして、何実際に起こったのことですtring '北京 ''北京111'に置き換えられず、結果セットに残っています。

理由は、文字列リテラル'北京 'それらがある場合(表定義によって決定される)GBKを使用して符号化され、(セッションによって決定される)utf8mb4フィールド城市から文字列値'北京 'を使用して符号化されますバイナリに変換された場合、それらはすべてのバイトでは同じではありませんが、2つの文字列は実際にすべての文字と意味的に同じです(基礎となるエンコーディング方法が使用されているかどうかにかかわらず)。

したがって、MySQLで厳密に文字列を比較する意味的に正しい方法は何ですか?

答えて

0

TRIM()文字列の先頭と最後から空白を削除する関数を参照してください。

gbkとutf8mb4を変換すると、変換テーブルが表示されます。あなたは希望の音訳を得ることができます(またはそうでないかもしれません)。

'北京'は、UTF8/utf8mb4
'北京 '用HEX E58C97 E4BAACは、UTF8/utf8mb4ためHEX E58C97 E4BAAC 20である - クエリ
'北京'に見られるようGBK
'北京 'ためHEX B1B1 BEA9あるGBKためHEX B1B1 BEA9 20ある - に見られるようにテーブル

SELECT ... BINARY '北京 ' ...と言うとき、文字列のエンコーディングは接続に基づいており、列エンコーディングには基づいていません。だからそれはutf8mb4です。

代わりの... WHEN BINARY 城市 = BINARY '北京 ' THEN ...、これらのいずれかを実行します。

プランAを、変換は自動的に発生してみましょう:... WHEN 城市 = '北京 ' THEN ...

プランB、明示的に変換します。... WHEN 城市 = CONVERT('北京 ' USING gbk) THEN ...

プランC、使用HEX:... WHEN HEX(城市) = HEX(CONVERT('北京 ' USING gbk)) THEN ...

計画D、あなたの試みに近い:... WHEN BINARY 城市 = BINARY(CONVERT('北京 ' USING gbk)) THEN ...

COLLATE utf8_binCOLLATE gbk_binなどを使用する他の方法があります。

+0

私は上記の計画Dは私の意図に近いと思いますが、データベースの指定フィールドがgbkを使ってエンコードされていることを知る必要があります。だから私はそれがこのことを行うのに十分な方法だとは思わない...まだ、あなたの助けのためにthx :) – luochen1990

関連する問題