[解決済み] [解答】イコール(=)vsライク(LIKE)
質問
SQLを使用する場合、以下のような利点があります。
=
の中に
WHERE
節ではなく
LIKE
?
特別な演算子を使用しない場合。
LIKE
と
=
は同じですよね?
どのように解決するのですか?
異なる演算子
LIKE
と
=
は異なる演算子です。ここでのほとんどの回答は、ワイルドカードのサポートに焦点を当てていますが、それはこれらの演算子の唯一の違いではありません!
=
は、数値と文字列を操作する比較演算子です。文字列を比較する場合、比較演算子は
文字列全体
.
LIKE
は文字列演算子で
一文字ずつ
.
問題を複雑にするために、どちらの演算子も 照合 これは比較の結果に重要な影響を与える可能性があります。
参考例
まず、これらの演算子が明らかに異なる結果をもたらす例を挙げてみよう。MySQL のマニュアルから引用させていただきます。
<ブロッククオート標準SQLでは、LIKEは文字単位でマッチングを行うので、=比較演算子とは異なる結果を出すことができます。
mysql> SELECT 'ä' LIKE 'ae' COLLATE latin1_german2_ci;
+-----------------------------------------+
| 'ä' LIKE 'ae' COLLATE latin1_german2_ci |
+-----------------------------------------+
| 0 |
+-----------------------------------------+
mysql> SELECT 'ä' = 'ae' COLLATE latin1_german2_ci;
+--------------------------------------+
| 'ä' = 'ae' COLLATE latin1_german2_ci |
+--------------------------------------+
| 1 |
+--------------------------------------+
なお、MySQLマニュアルのこのページでは
文字列比較関数
であり
=
が議論されていないことから、暗に
=
は厳密には文字列比較関数ではありません。
どのように
=
動作は?
は
SQLスタンダード§8.2
はどのように記述されているか
=
は文字列を比較します。
2つの文字列の比較は、以下のように決定されます。
a) Xの文字の長さが,Xの文字の長さと等しくない場合 は、短い方の文字列を実質的にYとする。 比較のために、そのコピーに置き換える。 の長さに拡張されたものである。 文字列の右側に1つ以上のパッドが連結され ここで、パッド文字は CS に基づいて選択される。この場合 CSがNO PAD属性を持っている場合、パッド文字は どの文字とも異なる実装依存の文字 XおよびYの文字セット中の文字で、照合数が少ないもの。 CS の下のどの文字列よりも小さい。それ以外の場合、パッド文字は <space> です。
b) XとYの比較の結果は,次のように与えられる。 照合順序 CS。
c) 照合順序によっては、2つの文字列は、その文字列に対応する文字列を含む。 長さが異なっていても、等しいものとして比較されます。 は、異なる文字列を含む。演算 MAX、MIN、DISTINCT、グループ化カラムの参照、そして UNION、EXCEPT、INTERSECT 演算子は、文字列を参照します。 文字列の中から、これらの操作によって選択される特定の値。 等しい値の集合は、実装に依存する。
(中略)
これはどういうことでしょうか。それは、文字列を比較するときに
=
演算子は、現在の照合順序の薄いラッパーに過ぎません。照合順序とは、文字列を比較するためのさまざまな規則を持つライブラリのことです。以下はその例です。
MySQL のバイナリ照合順序
:
static int my_strnncoll_binary(const CHARSET_INFO *cs __attribute__((unused)),
const uchar *s, size_t slen,
const uchar *t, size_t tlen,
my_bool t_is_prefix)
{
size_t len= MY_MIN(slen,tlen);
int cmp= memcmp(s,t,len);
return cmp ? cmp : (int)((t_is_prefix ? len : slen) - tlen);
}
この照合順序はバイト単位で比較するものです(これが"binary"と呼ばれる理由です - 文字列に特別な意味を与えるものではありません)。他の照合順序ではもっと高度な比較ができるかもしれません。
例えば、以下は
UTF-8 照合順序
大文字小文字を区別しない比較をサポートしています。コードが長すぎてここに貼り付けることはできませんが、そのリンク先に移動して
my_strnncollsp_utf8mb4()
. この照合順序は、一度に複数のバイトを処理することができ、さまざまな変換(大文字小文字を区別しない比較など)を適用することができます。この照合順序は
=
演算子は、照合順序のばらつきから完全に抽象化されています。
どのように
LIKE
動作は?
は
SQLスタンダード§8.5
はどのように記述されているか
LIKE
は文字列を比較します。
述語>
M LIKE P
は、Mを部分文字列に分割したものが存在する場合、真となります。 というような。
i) Mの部分文字列は、0個以上の連続した Mの<文字表現>であり、各<文字表現>である。 Mの表現>はちょうど1つの部分文字列の一部である。
ii) P の i 番目の部分文字列指定子が任意のものである場合 文字指定子、M の i 番目の部分文字列は、任意の単一の <文字表現>。
iii) Pのi番目の部分文字列指定子が任意の文字列である場合 の任意のシーケンスである。 0以上の<文字表現>である。
iv) P の i 番目の部分文字列指定子が、以下のいずれでもない場合 任意の文字指定子または任意の文字列指定子であること。 Mのi番目の部分文字列は、その部分文字列と等しい。 の照合順序にしたがって、指定子 のような述語があり、その場合、<space>.は付加されない。 と同じ長さの文字列を持つ。 指定子で指定します。
v) Mの部分文字列の数は、Mの部分文字列の数に等しい。 Pの部分文字列指定子。
(強調)
これはかなり語感がいいので、分解してみましょう。項目ⅱとⅲは、ワイルドカードの
_
と
%
それぞれ もし
P
はワイルドカードを含まないので、項目ivのみが適用されます。これは、OPが提起した関心のあるケースです。
この場合、quot;substring" (個々の文字)を比較します。
M
のそれぞれの部分文字列に対して
P
を現在の照合順序で使用します。
結論
要は、文字列を比較するときに
=
は文字列全体を比較するのに対し
LIKE
は1文字ずつ比較します。どちらの比較も現在の照合順序を使用します。この違いは、この投稿の最初の例で証明されているように、いくつかのケースで異なる結果につながります。
どちらを使うべきですか?それは誰も教えてくれません。あなたのユースケースに合ったものを使う必要があるのです。比較演算子を切り替えて、早急に最適化することはありません。
関連
-
[解決済み] SQLクエリで2つの列から値を引き算する
-
[解決済み] SQL ServerでSELECTからUPDATEする方法とは?
-
[解決済み] callとapplyの違いは何ですか?
-
[解決済み] SQLiteのINSERT/per-secondのパフォーマンスを向上させる
-
[解決済み] PHPでSQLインジェクションを防ぐにはどうしたらいいですか?
-
[解決済み] Python 3で「1000000000000000 in range(1000000000000001)」はなぜ速いのですか?
-
[解決済み] MongoDBに "like "を使ってクエリを実行する方法
-
[解決済み] ...値に挿入する ( SELECT ... FROM ... )
-
[解決済み] JOINとINNER JOINの違いについて
-
[解決済み] INNER JOINよりもCROSS APPLYを使用すべきなのはどのような場合ですか?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】「パラメータ@objnameがあいまいか、主張する@objtype(COLUMN)が間違っています」を解決するにはどうすればよいですか?[重複している]。
-
[解決済み】''付近の構文が正しくない
-
[解決済み】2つの列を分割する方法は?
-
[解決済み】参照するテーブルにプライマリーキーやキャンディデートキーがない
-
[解決済み】sys.dm_exec_sql_textはどのように機能するのでしょうか?
-
[解決済み] INSERT ステートメントが FOREIGN KEY 制約と競合する - SQL Server
-
[解決済み] DELETE文の競合REFERENCE制約
-
[解決済み] エラー: 名前解析スクリプトで正しい関数に渡された長さのパラメーターが無効です。
-
[解決済み] ora-06553 pls-306 'ogc_x' の呼び出しで引数の数または種類が誤っている。
-
[解決済み] CLOBとNCLOBの違いは何ですか?