1. ホーム
  2. sql

[解決済み] [解答】イコール(=)vsライク(LIKE)

2022-03-26 07:50:40

質問

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文字ずつ比較します。どちらの比較も現在の照合順序を使用します。この違いは、この投稿の最初の例で証明されているように、いくつかのケースで異なる結果につながります。

どちらを使うべきですか?それは誰も教えてくれません。あなたのユースケースに合ったものを使う必要があるのです。比較演算子を切り替えて、早急に最適化することはありません。