SQL Server ignoriert Groß- und Kleinschreibung in einem where-Ausdruck

87

Wie erstelle ich eine SQL-Abfrage (MS SQL Server), bei der bei der "where" -Klausel die Groß- und Kleinschreibung nicht berücksichtigt wird?

SELECT * FROM myTable WHERE myField = 'sOmeVal'

Ich möchte, dass die Ergebnisse zurückkommen und den Fall ignorieren

Raul Agrait
quelle

Antworten:

132

In der Standardkonfiguration einer SQL Server-Datenbank wird bei Zeichenfolgenvergleichen die Groß- und Kleinschreibung nicht berücksichtigt. Wenn Ihre Datenbank diese Einstellung überschreibt (mithilfe einer alternativen Sortierung), müssen Sie angeben, welche Art von Sortierung in Ihrer Abfrage verwendet werden soll.

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

Beachten Sie, dass die von mir bereitgestellte Zusammenstellung nur ein Beispiel ist (obwohl sie höchstwahrscheinlich für Sie in Ordnung ist). Eine ausführlichere Übersicht über SQL Server-Kollatierungen finden Sie hier .

Adam Robinson
quelle
Nur um dies zu bestätigen, muss dies nur einmal am Ende der WHEREAnweisung hinzugefügt werden und wirkt sich auf alle WHEREKlauseln aus, richtig?
Ashleedawg
Möchten Sie wissen, ob Ihre Antwort Leistungsprobleme aufweist, indem Sie einen Spaltenwert in einen Groß- UPPERoder LOWERKleinschreibung konvertieren oder dann die LIKESuchfunktion verwenden?
Shaijut
1
@ashleedawg - gute Frage .. es scheint eine Einstellung pro Zeile zu sein.
Leo Gurdian
29

Bei Zeichenfolgenvergleichen wird normalerweise die Groß- und Kleinschreibung nicht berücksichtigt. Wenn Ihre Datenbank für die Sortierung konfiguriert ist, bei der zwischen Groß- und Kleinschreibung unterschieden wird, müssen Sie die Verwendung einer Sortierung ohne Berücksichtigung der Groß- und Kleinschreibung erzwingen:

SELECT balance FROM people WHERE email = '[email protected]'
  COLLATE SQL_Latin1_General_CP1_CI_AS 
Andrejs Cainikovs
quelle
@ AskeB. und Andrejs: Dies ist technisch gesehen kein Problem mit der Datenbankkonfiguration. Weitere Informationen zu Zeichenfolgenvergleichen finden Sie in meiner Antwort .
Solomon Rutzky
22

Ich habe anderswo eine andere Lösung gefunden; das heißt, zu verwenden

upper(@yourString)

Aber alle hier sagen, dass es in SQL Server keine Rolle spielt, weil der Fall sowieso ignoriert wird. Ich bin mir ziemlich sicher, dass in unserer Datenbank zwischen Groß- und Kleinschreibung unterschieden wird.

Danny
quelle
5
Sie haben Recht, dass eine Datenbank zwischen Groß- und Kleinschreibung unterscheiden kann, aber dies ist ziemlich ineffizient, selbst wenn es benötigt wird. COLLATE ist das zu verwendende Schlüsselwort.
Mjaggard
1
Danke, dass du das angesprochen hast, @mjaggard. Ich hoffe, Sie oder jemand, der meine Antwort abzulehnen scheint, arbeiten zum Wohle von jemandem wie mir aus, der nach Antworten wie meiner sucht und diese findet.
Danny
1
Ich habe dies positiv bewertet, da es eine vollkommen rationale Erklärung ist. Sortieren riecht nach zu viel Aufwand und was ist, wenn Ihre Zeichenfolge Zeichen enthält, die die Sortierung nicht versteht? Latein 1 ist ein mieses Kodierungsschema. Viel Glück beim Erreichen aussagekräftiger Ergebnisse, wenn Ihre Saite einen Apostroph enthält (wie: O'Brien).
Eggmatters
2
Auch positiv bewertet. Ich kann mir viele Fälle vorstellen, in denen dies nützlich wäre. Darüber hinaus gibt es oft mehr als einen guten Weg, etwas zu tun.
Inversus
1
Das Ändern der Zeichenfolge von Zeichenfolgen zu Vergleichszwecken ist im Allgemeinen schlecht. In einigen Sprachen werden keine Konvertierungen durchgeführt. dh UNTER (x)! = UNTER (OBEN (x)).
Ceisc
12

Die Top-2-Antworten (von Adam Robinson und Andrejs Cainikovs ) sind insofern irgendwie richtig, als sie technisch funktionieren, aber ihre Erklärungen sind falsch und können daher in vielen Fällen irreführend sein. Während die SQL_Latin1_General_CP1_CI_ASSortierung beispielsweise in vielen Fällen funktioniert, sollte nicht davon ausgegangen werden, dass es sich um die geeignete Sortierung handelt, bei der die Groß- und Kleinschreibung nicht berücksichtigt wird. Angesichts der Tatsache, dass das OP in einer Datenbank mit einer Sortierung arbeitet, bei der zwischen Groß- und Kleinschreibung unterschieden wird (oder möglicherweise binär), wissen wir, dass das OP nicht die Kollatierung verwendet, die bei so vielen Installationen (insbesondere bei Installationen auf einem Betriebssystem) die Standardeinstellung ist mit US-Englisch als Sprache) : SQL_Latin1_General_CP1_CI_AS. Sicher, das OP könnte verwenden SQL_Latin1_General_CP1_CS_AS, aber bei der Arbeit mitVARCHARDaten ist es wichtig, die Codepage nicht zu ändern, da dies zu Datenverlust führen kann. Dies wird durch das Gebietsschema / die Kultur der Kollatierung gesteuert (z. B. Latin1_General vs French vs Hebrew usw.). Bitte beachten Sie Punkt 9 unten.

Die anderen vier Antworten sind in unterschiedlichem Maße falsch.

Ich werde alle Missverständnisse hier klären, damit die Leser hoffentlich die am besten geeigneten / effizientesten Entscheidungen treffen können.

  1. Nicht verwenden UPPER(). Das ist völlig unnötige zusätzliche Arbeit. Verwenden Sie eine COLLATEKlausel. In beiden Fällen muss ein Zeichenfolgenvergleich durchgeführt werden. Bei der Verwendung UPPER()muss jedoch auch zeichenweise überprüft werden, ob eine Zuordnung in Großbuchstaben vorliegt, und diese dann geändert werden. Und das müssen Sie auf beiden Seiten tun. Durch COLLATEdas Hinzufügen wird die Verarbeitung einfach angewiesen, die Sortierschlüssel nach einem anderen Regelsatz als standardmäßig zu generieren. Die Verwendung COLLATEist definitiv effizienter (oder "performant", wenn Sie dieses Wort mögen :) als die Verwendung UPPER(), wie in diesem Testskript (auf PasteBin) bewiesen .

    Es gibt auch das Problem , das @Ceisc in der Antwort von @ Danny festgestellt hat:

    In einigen Sprachen werden keine Konvertierungen durchgeführt. dh UNTER (x)! = UNTER (OBEN (x)).

    Das türkische Großbuchstaben "İ" ist das übliche Beispiel.

  2. Nein, die Sortierung ist keine datenbankweite Einstellung, zumindest nicht in diesem Zusammenhang. Es gibt eine Standardkollatierung auf Datenbankebene, die als Standard für geänderte und neu erstellte Spalten verwendet wird, in denen die COLLATEKlausel nicht angegeben ist (was wahrscheinlich der Grund für dieses häufige Missverständnis ist). Sie wirkt sich jedoch nur dann direkt auf Abfragen aus, wenn Sie es sind Wenn Sie Zeichenfolgenliterale und -variablen mit anderen Zeichenfolgenliteralen und -variablen vergleichen, verweisen Sie auf Metadaten auf Datenbankebene.

  3. Nein, die Sortierung erfolgt nicht pro Abfrage.

  4. Kollatierungen sind pro Prädikat (dh etwas Operand etwas) oder Ausdruck, nicht pro Abfrage. Dies gilt für die gesamte Abfrage, nicht nur für die WHEREKlausel. Dies umfasst JOINs, GROUP BY, ORDER BY, PARTITION BY usw.

  5. Nein, konvertieren Sie aus folgenden Gründen nicht zu VARBINARY(z. B. convert(varbinary, myField) = convert(varbinary, 'sOmeVal')):

    1. Das ist ein binärer Vergleich, bei dem die Groß- und Kleinschreibung nicht berücksichtigt wird (worum es in dieser Frage geht).
    2. Wenn Sie einen binären Vergleich wünschen, verwenden Sie eine binäre Sortierung. Verwenden Sie eine, die mit endet, _BIN2wenn Sie SQL Server 2008 oder höher verwenden. Andernfalls haben Sie keine andere Wahl, als eine zu verwenden, die mit endet _BIN. Wenn die Daten vorhanden sind, spielt NVARCHARes keine Rolle, welches Gebietsschema Sie verwenden, da sie in diesem Fall alle gleich sind und daher Latin1_General_100_BIN2immer funktionieren. Wenn die Daten VARCHAR, müssen Sie das gleiche Gebietsschema verwenden , dass die Daten aktuell (zB Latin1_General, French, Japanese_XJISusw.) , da die locale die Codepage bestimmt , die verwendet wird, und Seiten Code ändern können die Daten (dh Datenverlust) ändern.
    3. Die Verwendung eines Datentyps variabler Länge ohne Angabe der Größe hängt von der Standardgröße ab. Je nach Kontext, in dem der Datentyp verwendet wird, gibt es zwei unterschiedliche Standardeinstellungen. Es ist entweder 1 oder 30 für Zeichenfolgentypen. Bei Verwendung CONVERT()wird der Standardwert 30 verwendet. Die Gefahr besteht darin, dass die Zeichenfolge, wenn sie länger als 30 Byte sein kann, stillschweigend abgeschnitten wird und Sie wahrscheinlich falsche Ergebnisse von diesem Prädikat erhalten.
    4. Selbst wenn Sie einen Vergleich zwischen Groß- und Kleinschreibung wünschen, wird bei binären Kollatierungen nicht zwischen Groß- und Kleinschreibung unterschieden (ein weiteres sehr häufiges Missverständnis).
  6. Nein, unterscheidet LIKEnicht immer zwischen Groß- und Kleinschreibung. Es verwendet die Sortierung der Spalte, auf die verwiesen wird, oder die Sortierung der Datenbank, wenn eine Variable mit einem Zeichenfolgenliteral verglichen wird, oder die Sortierung, die über die optionale COLLATEKlausel angegeben wird.

  7. LCASEist keine SQL Server-Funktion. Es scheint entweder Oracle oder MySQL zu sein. Oder möglicherweise Visual Basic?

  8. Da der Kontext der Frage darin besteht, eine Spalte mit einem Zeichenfolgenliteral zu vergleichen, haben hier weder die Sortierung der Instanz (häufig als "Server" bezeichnet) noch die Sortierung der Datenbank direkte Auswirkungen. Kollatierungen werden für jede Spalte gespeichert, und jede Spalte kann eine andere Kollatierung haben. Diese Kollatierungen müssen nicht mit der Standardkollatierung der Datenbank oder der Kollatierung der Instanz identisch sein. Sicher, die Instanzkollatierung ist die Standardeinstellung für das, was eine neu erstellte Datenbank als Standardkollatierung verwendet, wenn die COLLATEKlausel beim Erstellen der Datenbank nicht angegeben wurde. Ebenso wird die Standardkollatierung der Datenbank von einer geänderten oder neu erstellten Spalte verwendet, wenn die COLLATEKlausel nicht angegeben wurde.

  9. Sie sollten die Sortierung ohne Berücksichtigung der Groß- und Kleinschreibung verwenden, die ansonsten der Sortierung der Spalte entspricht. Verwenden Sie die folgende Abfrage, um die Sortierung der Spalte zu ermitteln (ändern Sie den Namen der Tabelle und den Schemanamen):

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

    Dann ändere einfach das _CSSein _CI. Also Latin1_General_100_CS_ASwürde werden Latin1_General_100_CI_AS.

    Wenn die Spalte eine binäre Kollatierung verwendet (die mit _BINoder endet _BIN2), suchen Sie eine ähnliche Kollatierung mithilfe der folgenden Abfrage:

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

    Angenommen, die Spalte verwendet Japanese_XJIS_100_BIN2: Gehen Sie folgendermaßen vor:

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

Weitere Informationen zu Kollatierungen, Codierungen usw. finden Sie unter: Kollatierungsinformationen

Solomon Rutzky
quelle
7

Nein, nur die Verwendung LIKEfunktioniert nicht. LIKESucht nach Werten, die genau Ihrem angegebenen Muster entsprechen. In diesem Fall LIKEwürde nur der Text 'sOmeVal' und nicht 'someval' gefunden.

Eine praktikable Lösung ist die Verwendung der LCASE()Funktion. LCASE('sOmeVal')Ruft die Kleinbuchstaben Ihres Textes ab: 'someval'. Wenn Sie diese Funktion für beide Seiten Ihres Vergleichs verwenden, funktioniert sie:

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

Die Anweisung vergleicht zwei Kleinbuchstaben, sodass Ihr 'sOmeVal' mit jeder anderen Notation von 'someval' übereinstimmt (z. B. 'Someval', 'sOMEVAl' usw.).

David Hermanns
quelle
7
In 99,9% der SQL Server-Installationen, die mit _CI sortiert sind, unterscheidet LIKE nicht zwischen Groß- und Kleinschreibung.
RichardTheKiwi
1
Heutzutage heißt die Funktion UNTER
David Brossard
@ DavidBrossard und David Hermanns, ich glaube nicht, dass es jemals LCASE()in SQL Server war (zumindest nicht, dass ich sehen kann). Ich denke, diese Antwort ist für ein ganz anderes RDBMS. Weitere Informationen zu Zeichenfolgenvergleichen finden Sie in meiner Antwort .
Solomon Rutzky
3

Sie können die Groß- und Kleinschreibung erzwingen und auf eine solche Varbinary umwandeln:

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

quelle
3
Dies ist zwar funktional, aber kein empfehlenswerter Ansatz. Kollatierungen dienen zum Verwalten von Sortier- und Zeichenfolgenvergleichen.
Adam Robinson
@AdamRobinson geht es nicht um "String-Vergleiche"?
Fandango68
@ Fandango68 Ja, und Adam sagt, dass Kollatierungen besser sind, wenn String-Vergleiche durchgeführt werden.
JLRishe
@ Fandango68 Diese Antwort ist auf mehreren Ebenen falsch. Bitte sehen Sie meine Antwort für Details, insbesondere Punkt 5.
Solomon Rutzky
@AdamRobinson Weitere Informationen zu Zeichenfolgenvergleichen finden Sie in meiner Antwort .
Solomon Rutzky
2

In welcher Datenbank befinden Sie sich? Bei MS SQL Server handelt es sich um eine datenbankweite Einstellung, oder Sie können sie pro Abfrage mit dem Schlüsselwort COLLATE überschreiben.

Chase Seibert
quelle
Hallo. Für SQL Server handelt es sich in Bezug auf diese Frage weder um eine datenbankweite Einstellung noch um eine Abfrage pro Abfrage. Bitte sehen Sie meine Antwort für Details.
Solomon Rutzky