SQLサーバーはwhere式の大文字小文字を無視します


回答:


135

SQL Serverデータベースの既定の構成では、文字列の比較で大文字と小文字が区別されません。データベースが(代替照合を使用して)この設定を上書きする場合は、クエリで使用する照合の種類を指定する必要があります。

SELECT * FROM myTable WHERE myField = 'sOmeVal' COLLATE SQL_Latin1_General_CP1_CI_AS

私が提供した照合は単なる例であることに注意してください(ただし、おそらく問題なく機能します)。SQL Server照合のより完全な概要は、ここにあります


確認のために、これはWHEREステートメントの最後に1回追加するだけでよく、すべてのWHERE句に影響しますよね?
ashleedawg 2018年

知っているように、あなたの答えは、列に値変換することにより、任意のパフォーマンスの問題を持っていないUPPERか、LOWER使用して、その後ケースをLIKE検索しますか?
shaijut 2018

1
@ ashleedawg-良い質問です。行ごとの設定のようです。
レオガーディアン

29

通常、文字列の比較では大文字と小文字は区別されません。データベースで大文字と小文字を区別する照合順序が構成されている場合は、大文字と小文字を区別しない照合順序を強制的に使用する必要があります。

SELECT balance FROM people WHERE email = 'billg@microsoft.com'
  COLLATE SQL_Latin1_General_CP1_CI_AS 

@AskeB。Andrejs:これは技術的にはデータベース構成の問題ではありません。文字列の比較の説明については、私の回答を参照しください。
SolomonRutzky19年

21

私は他の場所で別の解決策を見つけました。つまり、使用する

upper(@yourString)

しかし、ここの誰もが、SQL Serverでは、とにかく大文字と小文字を区別しないので、それは問題ではないと言っていますか?私たちのデータベースでは大文字と小文字が区別されると確信しています。


6
データベースで大文字と小文字を区別できることは正しいですが、必要な場合でも、これはかなり非効率的です。COLLATEは使用するキーワードです。
mjaggard 2012年

1
@mjaggardさん、ご紹介いただきありがとうございます。あなた、または私の答えに反対しているように見える人が、私のような答えを探して見つけた私のような人のために詳しく説明してくれることを願っています。
ダニー

1
それは完全に合理的な説明であるため、これを支持しました。オーバーヘッドが多すぎるスマックを照合します。文字列に照合で理解できない文字が含まれている場合はどうなりますか?ラテン1はお粗末なエンコード方式です。文字列にアポストロフィが含まれている場合は、意味のある結果が得られます(Like:O'Brien)。
eggmatters 2013

2
同様に賛成。これが役立つケースはたくさん考えられます。さらに、何かをするための良い方法が複数あることがよくあります。
インバーサス2013

1
比較のために文字列の大文字と小文字を変更することは、一般的に悪いことです。一部の言語では、変換はラウンドトリップしません。つまり、LOWER(x)!= LOWER(UPPER(x))です。
ceisc 2016年

14

(からトップ2の回答アダム・ロビンソンAndrejs Cainikovsは、彼らは技術的に作業を行うことで)、正しいみかん、ちょっとですが、その説明は間違っているので、多くの場合、誤解を招くことができます。たとえば、SQL_Latin1_General_CP1_CI_AS照合は多くの場合機能しますが、大文字と小文字を区別しない適切な照合であると見なすべきではありません。実際、OPが大文字と小文字を区別する(または場合によってはバイナリの)照合順序でデータベースで動作していることを考えると、OPは非常に多くのインストール(特にOSにインストールされているもの)のデフォルトである照合順序を使用していないことがわかります)言語として英語を使用して:SQL_Latin1_General_CP1_CI_AS。確かに、OPを使用している可能性がありますSQL_Latin1_General_CP1_CS_ASが、VARCHARデータの場合、データの損失につながる可能性があるため、コードページを変更しないことが重要です。これは、照合のロケール/カルチャによって制御されます(つまり、Latin1_General、フランス語、ヘブライ語など)。下記のポイント9をご覧ください。

他の4つの答えはさまざまな程度で間違っています。

読者が最も適切で効率的な選択を行えるように、ここですべての誤解を明らかにします。

  1. 使用しないでくださいUPPER()。それは完全に不要な余分な作業です。COLLATE句を使用します。どちらの場合も文字列の比較を行う必要がありますが、を使用UPPER()すると、大文字のマッピングがあるかどうかを文字ごとに確認してから変更する必要があります。そして、あなたは両側でこれを行う必要があります。追加COLLATEは、デフォルトで行われていたものとは異なるルールのセットを使用してソートキーを生成するように処理を指示するだけです。このテストスクリプト(PasteBin)で証明されCOLLATEているように、使用する方が、使用するよりも間違いなく効率的です(または、その単語が好きな場合は「パフォーマンスが高い」:) 。UPPER()

    @Dannyの回答について@Ceiscが指摘した問題もあります。

    一部の言語では、変換はラウンドトリップしません。つまり、LOWER(x)!= LOWER(UPPER(x))です。

    トルコ語の大文字の「İ」が一般的な例です。

  2. いいえ、少なくともこのコンテキストでは、照合はデータベース全体の設定ではありません。データベースレベルのデフォルトの照合があり、COLLATE句を指定しない変更および新しく作成された列のデフォルトとして使用されます(これは、この一般的な誤解が原因である可能性があります)が、そうでない限り、クエリに直接影響しません。文字列リテラルと変数を他の文字列リテラルと変数と比較するか、データベースレベルのメタデータを参照しています。

  3. いいえ、照合はクエリごとではありません。

  4. 照合は、クエリごとではなく、述語(つまり、何かオペランド何か)または式ごとに行われます。そして、これはWHERE句だけでなくクエリ全体にも当てはまります。これには、JOIN、GROUP BY、ORDER BY、PARTITIONBYなどが含まれます。

  5. いいえ、次の理由でVARBINARY(などconvert(varbinary, myField) = convert(varbinary, 'sOmeVal'))に変換しないでください。

    1. これはバイナリ比較であり、大文字と小文字は区別されません(これがこの質問で求められていることです)
    2. バイナリ比較が必要な場合は、バイナリ照合を使用してください。_BIN2SQL Server 2008以降を使用している場合は、で終わるものを使用してください。それ以外の場合は、で終わるものを使用するしかありません_BIN。データがそうである場合、NVARCHARそれらはすべて同じであるため、どのロケールを使用してもかまいませんLatin1_General_100_BIN2。したがって、常に機能します。データがある場合VARCHAR、あなたはデータ(例えば、現在あるのと同じロケールを使用する必要がありLatin1_GeneralFrenchJapanese_XJISロケールが使用されているコードページを決定し、コードページを変更するとデータ(データの損失)を変えることができるので、など)。
    3. サイズを指定せずに可変長データ型を使用すると、デフォルトサイズに依存し、データ型が使用されているコンテキストに応じて2つの異なるデフォルトがあります。文字列タイプの場合は1または30です。一緒CONVERT()に使用すると、デフォルト値の30が使用されます。危険なのは、文字列が30バイトを超える可能性がある場合、文字列がサイレントに切り捨てられ、この述語から誤った結果が得られる可能性があることです。
    4. 大文字と小文字を区別する比較が必要な場合でも、バイナリ照合は大文字と小文字を区別しません(別の非常に一般的な誤解)。
  6. いいえ、LIKE常に大文字と小文字が区別されるとは限りません。参照されている列の照合、変数が文字列リテラルと比較される場合はデータベースの照合、またはオプションのCOLLATE句で指定された照合を使用します。

  7. LCASESQLServerの関数ではありません。OracleまたはMySQLのいずれかであるように見えます。それともVisualBasic?

  8. 質問のコンテキストは列を文字列リテラルと比較することであるため、インスタンスの照合(「サーバー」と呼ばれることが多い)もデータベースの照合もここでは直接的な影響はありません。照合順序は列ごとに格納され、各列は異なる照合順序を持つことができ、それらの照合順序はデータベースのデフォルトの照合順序またはインスタンスの照合順序と同じである必要はありません。確かに、インスタンス照合はCOLLATE、データベースの作成時に句が指定されていない場合に、新しく作成されたデータベースがデフォルトの照合として使用するデフォルトです。同様に、データベースのデフォルトの照合順序は、COLLATE句が指定されていない場合に変更または新しく作成された列が使用するものです。

  9. 大文字と小文字を区別しない照合を使用する必要があります。それ以外の点では、列の照合と同じです。次のクエリを使用して、列の照合順序を検索します(テーブルの名前とスキーマ名を変更します)。

    SELECT col.*
    FROM   sys.columns col
    WHERE  col.[object_id] = OBJECT_ID(N'dbo.TableName')
    AND    col.[collation_name] IS NOT NULL;
    

    次に、をに変更_CSします_CI。だから、Latin1_General_100_CS_ASになりLatin1_General_100_CI_ASます。

    列がバイナリ照合(_BINまたはで終わる_BIN2)を使用している場合は、次のクエリを使用して同様の照合を見つけます。

    SELECT *
    FROM   sys.fn_helpcollations() col
    WHERE  col.[name] LIKE N'{CurrentCollationMinus"_BIN"}[_]CI[_]%';
    

    たとえば、列がを使用していると仮定してJapanese_XJIS_100_BIN2、次のようにします。

    SELECT *
    FROM   sys.fn_helpcollations() col
    WHERE  col.[name] LIKE N'Japanese_XJIS_100[_]CI[_]%';
    

照合、エンコーディングなどの詳細については、以下をご覧ください:照合情報


7

いいえ、使用LIKEするだけでは機能しません。LIKE指定されたパターンに完全に一致する値を検索します。この場合LIKE、テキスト「sOmeVal」のみが検索され、「someval」は検索されません。

実用的な解決策は、LCASE()関数を使用することです。LCASE('sOmeVal')テキストの小文字の文字列を取得します: 'someval'。比較の両側でこの関数を使用すると、次のように機能します。

SELECT * FROM myTable WHERE LCASE(myField) LIKE LCASE('sOmeVal')

このステートメントは2つの小文字の文字列を比較するため、「sOmeVal」は「someval」の他のすべての表記と一致します(たとえば、「Someval」、「sOMEVAl」など)。


7
_CIで照合されるSQLServerインストールの99.9%では、LIKEでは大文字と小文字が区別されません。
RichardTheKiwi 2012年

1
現在、この関数はLOWERと呼ばれています
DavidBrossard19年

@DavidBrossardとDavidHermanns LCASE()、SQL Serverにはなかったと思います(少なくとも私が見ることはできません)。この答えは、まったく異なるRDBMSに対するものだと思います。文字列の比較の説明については、私の回答を参照しください。
SolomonRutzky19年

4

大文字と小文字を区別して、次のようなvarbinaryにキャストできます。

SELECT * FROM myTable 
WHERE convert(varbinary, myField) = convert(varbinary, 'sOmeVal')

3
これは機能的ですが、お勧めのアプローチではありません。照合順序は、並べ替えと文字列の比較を管理するためにあります。
アダムロビンソン

@AdamRobinsonは「文字列比較」についてではありませんか?
fandango68 2016

@ Fandongo68はい、そうです。Adamは、文字列の比較を行う場合は照合順序の方が優れていると言っています。
JLRishe 2018年

@ Fandango68この答えはいくつかのレベルで間違っています。見てください、私の答えは、詳細については、特に5ポイント
ソロモンRutzky

@AdamRobinson文字列比較の説明については、私の回答を参照しください。
SolomonRutzky19年

2

どのデータベースを使用していますか?MS SQL Serverでは、データベース全体の設定ですが、COLLATEキーワードを使用してクエリごとに上書きすることもできます。


こんにちは。SQL Serverの場合、この質問の内容に関しては、データベース全体の設定でもクエリごとの設定でもありません。詳細は私の回答をご覧ください。
SolomonRutzky19年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.