7

結果にとって末尾のスペースが重要なデータベースを構築しています。結果を照会すると、

SELECT * where `field` = 'a ' 

値が「a」のフィールドがある場合に結果を返します。結果セットで末尾のスペースが重要になるようにします。Char、Varchar、Text、および Blob を使用してみました。このフィールドはテーブルのインデックスであることに注意してください。

末尾の (および/または先頭の) スペースをカウントする方法でクエリを実行する方法を教えてもらえますか? これを機能させるために、特別な方法でテーブルをフォーマットする必要がありますか?

4

2 に答える 2

5

この動作は設計によるものであり、MySQL だけのものではありません。

を使用して比較で回避できますBINARY

mysql> select version(), 'a' = 'a ', BINARY 'a' = BINARY 'a ';
+-------------+------------+--------------------------+
| version()   | 'a' = 'a ' | BINARY 'a' = BINARY 'a ' |
+-------------+------------+--------------------------+
| 5.5.25a-log |          1 |                        0 |
+-------------+------------+--------------------------+
1 row in set (0.00 sec)

しかし、それ以上ではありません。SELECTこれは、検索へのユーザー入力などに空白が表示される場合に役立ちます。しかし、実際に空白で追跡された情報を入力したい場合は、問題になります ('a' と 'a' の両方を含むインデックスを持つことはできません)。

こちらもご覧ください

比較のために、varchar の末尾の空白を考慮する必要があります。

おそらく、その列の文字列を逆にして、表示するときに元に戻すことができます。もちろん、これはその列に基づく順序付けを破壊しますが、同等性または部分文字列の存在のみをテストする場合は、うまくいく可能性があります。先頭のスペースはカウントされます。

等価検索の場合、文字列の base64 エンコーディングを格納することもできます。これは、辞書編集順序を維持する必要があります (つまり、a と b の間の順序は、base64(a) と base64(b) の間で維持する必要があります)。または、文字列にターミネータを追加することもできます (「\n」はうまく機能し、検索に表示されません)。

最後に、人間は違いを見分けられないため危険です。スペースを UTF8 文字 (49824) に置き換えることができます。

mysql> select concat ('\'a', char(49824),'\'') AS tricked,
              concat ('\'a', ' '        ,'\'') as honest,
              concat ('\'a', char(49824),'\'') =
              concat ('\'a', ' '        ,'\'') as equals;

+---------+--------+--------+
| tricked | honest | equals |
+---------+--------+--------+
| 'a '    | 'a '   |      0 |
+---------+--------+--------+
1 row in set (0.00 sec)

行は等しいように見えますが、そうではありません。HTML ではスペースはスペースであり、49824 は (ノンブレーク スペース) であることに注意してください。これは、HTML との間で変換する関数に影響を与えます。nbsp が実際には UTF8 コードポイントであることは、正直な文字列が 2 バイトであることを意味しますが、だまされた文字列の長さは実際には3です。

最後に、のVARBINARY代わりに列を宣言できるVARCHARため、何が起こっているかを完全に隠すことができます。これは最も簡単な解決策のように見えますが、数週間または数か月後には苦しむ可能性があるのではないかと心配しています.

于 2012-09-22T10:41:44.233 に答える
1

私は次のことを成功させましたが、それが不安定なアプローチであるかどうかはわかりません。

CREATE TEMPORARY TABLE test (
  PRIMARY KEY(id),
  id INT AUTO_INCREMENT,
  val VARCHAR(20)
);

INSERT INTO test VALUES
(NULL, 'a'),
(NULL, 'a '),
(NULL, 'a  '),
(NULL, 'a   ');

SELECT * FROM test
WHERE val LIKE 'a ';

出力

id  val
2   'a '

WHERE val = 'a ' を使用すると、末尾のスペースを考慮せずにすべてのエントリが選択されますが、LIKE は機能します。

于 2012-09-22T10:59:58.787 に答える