Wie mache ich ein LIKE ohne Berücksichtigung der Groß- und Kleinschreibung in einer Datenbank mit Groß- und Kleinschreibung?
11
Mein Lieferant verlangt, dass in der Data Warehouse-Datenbank zwischen Groß- und Kleinschreibung unterschieden wird, ich muss jedoch zwischen Groß- und Kleinschreibung unterscheiden.
Wie würden Sie in einer Datenbank mit Groß- und Kleinschreibung die Groß- und Kleinschreibung beachten?
Sie können Ihrer ausgewählten Abfrage eine neue Sortierung hinzufügen, um zwischen Groß- und Kleinschreibung zu unterscheiden.
-- Case sensitive exampleSELECT*FROMTABLEWHERE Name collate SQL_Latin1_General_CP1_CS_AS like'%hospitalist%'-- Case insensitive exampleSELECT*FROMTABLEWHERE Name collate SQL_Latin1_General_CP1_CI_AS like'%hospitalist%'
Beachten Sie nur die möglichen Leistungsprobleme. Sie müssen den Clustered-Index scannen, um die Werte anzupassen / zu finden, wenn Sie die Sortierung durchführen. Die Art und Weise, wie Sie das LIKEStück schreiben, macht die Abfrage auch nicht sargable.
@stom Es gibt zwei Methoden. Entweder a) Verschieben Sie die Leistungsprobleme in die Verarbeitungszeit und nicht in die selectZeit. Sie können dies tun, indem Sie eine neue Spalte mit einer Teilmenge der transformierten Daten erstellen und diese dann indizieren, normalerweise zu Zeiten, in denen Sie ETL ausführen würden. Dies hätte Unterhaltskosten und ist keine gute Methode. B) Sie können die Abfragesuche streitig oder sargbar machen. Ändern der Abfrage so, dass sie funktioniert SELECT * FROM TABLE WHERE VALUE LIKE %hospitalistoder SELECT * FROM TABLE WHERE VALUE LIKE hospitalist%funktionieren würde. Abgesehen davon suchen Sie nach Hardware oder Funktionen, um die Geschwindigkeit bei schlechtem Design zu erhöhen.
Shaulinator
13
Während Sie können eine skalare Funktion wie verwenden UPPER oder LOWER und Sie können die Spalte so neu zusammenzustellen , dass es nicht mehr Groß- und Kleinschreibung ist, nähert sich diese alle Datenkonvertierung erforderlich gegen den Basisdaten erfolgen, die niemals versuchen , für einen Index ermöglicht. Sie führen Ihr LIKE auch mit einem Platzhalter an, sodass dies in diesem Szenario ohnehin nicht so wichtig für Sie ist, aber wenn Sie jemals effizient nach dem linken Teil einer Zeichenfolge suchen und den Optimierer berücksichtigen wollten Um einen Index zu durchsuchen, können Sie Ihre Zeichenfolge in Klammern ([]) wie folgt angeben:
SELECT*FROMTABLEWHERE Name LIKE'[hH][oO][sS][pP][iI][tT][aA][lL][iI][sS][tT]%'
CREATETABLE#tmp_cohellation_fun
(
ID INT IDENTITY(1,1)PRIMARYKEYCLUSTERED, myValue VARCHAR(50)COLLATE SQL_Latin1_General_CP1_CS_AS
)-- Garbage values to represent data you don't wantINSERTINTO#tmp_cohellation_fun
SELECT CAST(NEWID()AS VARCHAR(50))FROM master.sys.configurations t1
CROSSJOIN master.sys.configurations t2
CROSSJOIN master.sys.configurations t3;-- Sprinkle a little bit of good dataINSERTINTO#tmp_cohellation_fun
(myValue)VALUES('Apple'),('apple')-- Another healthy helping of garbage that we don't care aboutINSERTINTO#tmp_cohellation_fun
SELECT CAST(NEWID()AS VARCHAR(50))FROM master.sys.configurations t1
CROSSJOIN master.sys.configurations t2
CROSSJOIN master.sys.configurations t3;-- Some more good dataINSERTINTO#tmp_cohellation_fun
(myValue)VALUES('aPple'),('APPLE'),('APple')-- Final insert of garbage that we don't care aboutINSERTINTO#tmp_cohellation_fun
SELECT CAST(NEWID()AS VARCHAR(50))FROM master.sys.configurations t1
CROSSJOIN master.sys.configurations t2
CROSSJOIN master.sys.configurations t3
;-- Create a nonclustered rowstore indexCREATEINDEX ix_myValue ON#tmp_cohellation_fun (myValue);SETSTATISTICSXMLON;-- Seek, but incorrect resultsSELECT*FROM#tmp_cohellation_fun
WHERE myValue LIKE'apple%';-- Scan, with correct resultsSELECT*FROM#tmp_cohellation_fun
WHERE myValue COLLATE SQL_Latin1_General_CP1_CI_AS LIKE'apple%';-- Seek, with correct resultsSELECT*FROM#tmp_cohellation_fun
WHERE myValue LIKE'[aA][pP][pP][lL][eE]%';SETSTATISTICSXMLOFF;DROPTABLEIFEXISTS#tmp_cohellation_fun
Liebe es. Es ist mir ein Rätsel, warum SQL nicht einfach so elegant zurückgreifen kann, wenn Sie sagen, dass die Sortierung von Groß- und Kleinschreibung zu Groß- und Kleinschreibung nicht unterscheidet, wenn Sie zwei ansonsten identische Kollatierungen haben. Ich verstehe, warum du nicht in die andere Richtung gehen kannst. Jedenfalls ist das gutes Zeug.
John Leidegren
12
Sowohl dies als auch die COLLATEAntwort wirken sich auf die Leistung aus, da die Abfrage nicht SARG-fähig ist. Der einfachste Weg, dies zu tun (wie Edgar in einem Kommentar vorgeschlagen hat), ist jedoch:
select
Zeit. Sie können dies tun, indem Sie eine neue Spalte mit einer Teilmenge der transformierten Daten erstellen und diese dann indizieren, normalerweise zu Zeiten, in denen Sie ETL ausführen würden. Dies hätte Unterhaltskosten und ist keine gute Methode. B) Sie können die Abfragesuche streitig oder sargbar machen. Ändern der Abfrage so, dass sie funktioniertSELECT * FROM TABLE WHERE VALUE LIKE %hospitalist
oderSELECT * FROM TABLE WHERE VALUE LIKE hospitalist%
funktionieren würde. Abgesehen davon suchen Sie nach Hardware oder Funktionen, um die Geschwindigkeit bei schlechtem Design zu erhöhen.Während Sie können eine skalare Funktion wie verwenden UPPER oder LOWER und Sie können die Spalte so neu zusammenzustellen , dass es nicht mehr Groß- und Kleinschreibung ist, nähert sich diese alle Datenkonvertierung erforderlich gegen den Basisdaten erfolgen, die niemals versuchen , für einen Index ermöglicht. Sie führen Ihr LIKE auch mit einem Platzhalter an, sodass dies in diesem Szenario ohnehin nicht so wichtig für Sie ist, aber wenn Sie jemals effizient nach dem linken Teil einer Zeichenfolge suchen und den Optimierer berücksichtigen wollten Um einen Index zu durchsuchen, können Sie Ihre Zeichenfolge in Klammern ([]) wie folgt angeben:
Dieses Beispiel ( Link dbfiddle hier ) zeigt besser, was ich meine:
quelle
Sowohl dies als auch die
COLLATE
Antwort wirken sich auf die Leistung aus, da die Abfrage nicht SARG-fähig ist. Der einfachste Weg, dies zu tun (wie Edgar in einem Kommentar vorgeschlagen hat), ist jedoch:oder
quelle