web-dev-qa-db-ja.com

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

「where」句で大文字と小文字が区別されないSQLクエリ(MS SQL Server)を作成するにはどうすればよいですか?

SELECT * FROM myTable WHERE myField = 'sOmeVal'

ケースを無視して結果が戻ってくるようにしたい

78
Raul Agrait

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

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

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

121
Adam Robinson

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

SELECT balance FROM people WHERE email = '[email protected]'
  COLLATE SQL_Latin1_General_CP1_CI_AS 
28

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

upper(@yourString)

しかし、SQL Serverでは、とにかく大文字と小文字を無視しているので、それは問題ではありません。私たちのデータベースでは大文字と小文字が区別されると確信しています。

20
Danny

上位2つの回答( Adam Robinson および Andrejs Cainikovs から)は、技術的には機能しているという点で、ちょっと正確ですが、説明が間違っているため、誤解を招く可能性があります多くの場合。たとえば、SQL_Latin1_General_CP1_CI_AS照合は多くの場合に機能しますが、大文字と小文字を区別しない適切な照合であると想定するべきではありません。実際、OPが大文字と小文字を区別する(またはおそらくバイナリ)照合を使用してデータベースで動作していることを考えると、OPは多くのインストール(特にOSにインストールされているすべて)のデフォルトである照合を使用していないことがわかります言語として米国英語を使用))SQL_Latin1_General_CP1_CI_AS。確かに、OPcouldSQL_Latin1_General_CP1_CS_ASを使用していますが、VARCHARデータを使用する場合、データ損失につながる可能性があるため、コードページを変更しないことが重要です。 、それは照合のロケール/文化によって制御されます(つまり、Latin1_General vsフランス語vsヘブライ語など)。以下のポイント9を参照してください。

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

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

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

    問題もあります @ Dannyの回答で@Ceiscが指摘:

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

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

  2. いいえ、少なくともこのコンテキストでは、照合はデータベース全体の設定ではありません。データベースレベルの既定の照合順序があり、COLLATE句を指定しない変更され新しく作成された列の既定値として使用されます(この一般的な誤解はどこから来たのでしょう)。文字列リテラルと変数を他の文字列リテラルと変数と比較する場合、またはデータベースレベルのメタデータを参照する場合を除き、クエリに直接影響します。

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

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

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

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

  7. LCASEはSQL Server関数ではありません。 OracleまたはMySQLのようです。または、おそらくVisual Basicですか?

  8. 質問のコンテキストは列を文字列リテラルと比較するため、インスタンスの照合(「サーバー」と呼ばれることが多い)もデータベースの照合もdirectに影響を与えません。 。照合は各列ごとに保存され、各列は異なる照合を持つことができ、それらの照合はデータベースのデフォルト照合またはインスタンスの照合と同じである必要はありません。確かに、データベースの作成時に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_ASLatin1_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
Solomon Rutzky

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

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

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

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

7
David Hermanns

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

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

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

2
Chase Seibert