Jak skonstruować zapytanie SQL (MS SQL Server), w którym w klauzuli „where” nie jest rozróżniana wielkość liter?
SELECT * FROM myTable WHERE myField = 'sOmeVal'
Chcę, aby wyniki wróciły, ignorując sprawę
sql
sql-server
where-clause
case-insensitive
Raul Agrait
źródło
źródło
WHERE
oświadczenia i wpłynie to na wszystkieWHERE
klauzule, prawda?UPPER
lub wielkośćLOWER
liter, a następnie używającLIKE
do wyszukiwania?Zazwyczaj porównania ciągów nie uwzględniają wielkości liter. Jeśli twoja baza danych jest skonfigurowana do sortowania z rozróżnianiem wielkości liter, musisz wymusić użycie tej bez rozróżniania wielkości liter:
SELECT balance FROM people WHERE email = '[email protected]' COLLATE SQL_Latin1_General_CP1_CI_AS
źródło
Znalazłem inne rozwiązanie gdzie indziej; to znaczy do użycia
ale wszyscy tutaj mówią, że w SQL Server to nie ma znaczenia, ponieważ i tak ignoruje wielkość liter? Jestem prawie pewien, że w naszej bazie danych rozróżniana jest wielkość liter.
źródło
Dwie najważniejsze odpowiedzi (od Adama Robinsona i Andrejsa Cainikovsa ) są w pewnym sensie poprawne, ponieważ technicznie działają, ale ich wyjaśnienia są błędne i mogą być w wielu przypadkach mylące. Na przykład, chociaż
SQL_Latin1_General_CP1_CI_AS
w wielu przypadkach sortowanie zadziała, nie należy zakładać, że jest to właściwe sortowanie bez rozróżniania wielkości liter. W rzeczywistości, biorąc pod uwagę, że OP działa w bazie danych z rozróżnianiem wielkości liter (lub prawdopodobnie binarnych), wiemy, że OP nie używa sortowania, które jest domyślne dla tak wielu instalacji (szczególnie tych zainstalowanych w systemie operacyjnym za pomocą amerykańskiego angielskiego jako języka)SQL_Latin1_General_CP1_CI_AS
. Jasne, OP może być używanySQL_Latin1_General_CP1_CS_AS
, ale podczas pracy zVARCHAR
data, ważne jest, aby nie zmieniać strony kodowej, ponieważ może to prowadzić do utraty danych, a to jest kontrolowane przez ustawienia regionalne / kulturę zestawiania (tj. Latin1_General vs francuski vs hebrajski itp.). Zobacz punkt # 9 poniżej.Pozostałe cztery odpowiedzi są w różnym stopniu błędne.
Wyjaśnię tutaj wszystkie nieporozumienia, aby czytelnicy mogli, miejmy nadzieję, dokonać najbardziej odpowiednich / skutecznych wyborów.
Nie używaj
UPPER()
. To zupełnie niepotrzebna dodatkowa praca. UżyjCOLLATE
klauzuli. W obu przypadkach należy wykonać porównanie ciągów, ale za pomocą należyUPPER()
również sprawdzić, znak po znaku, czy występuje odwzorowanie na duże litery, a następnie je zmienić. I musisz to zrobić po obu stronach. DodawanieCOLLATE
po prostu kieruje przetwarzanie do generowania kluczy sortowania przy użyciu innego zestawu reguł niż domyślnie. UżywanieCOLLATE
jest zdecydowanie bardziej wydajne (lub "wydajne", jeśli lubisz to słowo :) niż używanieUPPER()
, jak udowodniono w tym skrypcie testowym (na PasteBin) .Jest też kwestia odnotowana przez @Ceisc w odpowiedzi @ Danny'ego:
Typowym przykładem jest turecka wielka litera „İ”.
Nie, sortowanie nie jest ustawieniem obejmującym całą bazę danych, a przynajmniej nie w tym kontekście. Istnieje domyślne sortowanie na poziomie bazy danych i jest używane jako domyślne dla zmienionych i nowo utworzonych kolumn, które nie określają
COLLATE
klauzuli (co jest prawdopodobne, skąd pochodzi to powszechne nieporozumienie), ale nie wpływa bezpośrednio na zapytania, chyba że porównywanie literałów łańcuchowych i zmiennych z innymi literałami łańcuchowymi i zmiennymi lub odwołujesz się do metadanych na poziomie bazy danych.Nie, sortowanie nie dotyczy zapytania.
Kolacje dotyczą predykatu (tj. Coś operandowego) lub wyrażenia, a nie zapytania. Dotyczy to całego zapytania, a nie tylko
WHERE
klauzuli. Obejmuje to POŁĄCZENIA, GRUPOWANIE, ZAMÓWIENIE, PARTYCJA WEDŁUG, itp.Nie, nie konwertuj na
VARBINARY
(np.convert(varbinary, myField) = convert(varbinary, 'sOmeVal')
) Z następujących powodów:_BIN2
jeśli używasz SQL Server 2008 lub nowszego, w przeciwnym razie nie masz innego wyboru, jak tylko użyć takiego, który kończy się na_BIN
. Jeśli dane są,NVARCHAR
to nie ma znaczenia, którego języka używasz, ponieważ w tym przypadku wszystkie są takie same, dlategoLatin1_General_100_BIN2
zawsze działają. Jeśli daneVARCHAR
, należy użyć tego samego ustawienia regionalne, że dane są obecnie (npLatin1_General
,French
,Japanese_XJIS
itp), ponieważ narodowe określa stronę kodową, która jest używana i zmianę stron kodowych może zmieniać dane (czyli utrata danych).CONVERT()
nim użyje wartości domyślnej 30. Niebezpieczeństwo polega na tym, że jeśli ciąg może mieć ponad 30 bajtów, zostanie po cichu obcięty i prawdopodobnie otrzymasz nieprawidłowe wyniki z tego predykatu.Nie,
LIKE
nie zawsze jest rozróżniana wielkość liter. Używa sortowania kolumny, do której się odwołuje, lub sortowania bazy danych, jeśli zmienna jest porównywana z literałem łańcuchowym, lub sortowania określonego za pomocąCOLLATE
klauzuli opcjonalnej .LCASE
nie jest funkcją programu SQL Server. Wygląda na to, że jest to Oracle lub MySQL. A może Visual Basic?Ponieważ kontekstem pytania jest porównanie kolumny z literałem łańcuchowym, ani sortowanie instancji (często nazywanej „serwerem”), ani sortowanie bazy danych nie mają tutaj bezpośredniego wpływu. Sortowania są przechowywane w każdej kolumnie, a każda kolumna może mieć inne sortowanie, a te sortowania nie muszą być takie same, jak domyślne sortowanie bazy danych lub sortowanie instancji. Jasne, sortowanie instancji jest domyślne dla tego, co nowo utworzona baza danych będzie używać jako domyślnego sortowania, jeśli
COLLATE
klauzula nie została określona podczas tworzenia bazy danych. Podobnie, domyślne sortowanie bazy danych jest tym, czego użyje zmieniona lub nowo utworzona kolumna, jeśliCOLLATE
klauzula nie zostanie określona.Należy użyć sortowania bez rozróżniania wielkości liter, które poza tym jest takie samo jak sortowanie kolumny. Użyj następującego zapytania, aby znaleźć sortowanie kolumny (zmień nazwę tabeli i nazwę schematu):
SELECT col.* FROM sys.columns col WHERE col.[object_id] = OBJECT_ID(N'dbo.TableName') AND col.[collation_name] IS NOT NULL;
Następnie wystarczy zmienić
_CS
się_CI
. TakLatin1_General_100_CS_AS
się stanieLatin1_General_100_CI_AS
.Jeśli kolumna używa sortowania binarnego (kończącego się na
_BIN
lub_BIN2
), znajdź podobne sortowanie, używając następującego zapytania:SELECT * FROM sys.fn_helpcollations() col WHERE col.[name] LIKE N'{CurrentCollationMinus"_BIN"}[_]CI[_]%';
Na przykład zakładając, że kolumna używa
Japanese_XJIS_100_BIN2
, wykonaj następujące czynności:SELECT * FROM sys.fn_helpcollations() col WHERE col.[name] LIKE N'Japanese_XJIS_100[_]CI[_]%';
Aby uzyskać więcej informacji na temat zestawień, kodowania itp., Odwiedź: Informacje o zestawieniach
źródło
Nie, tylko używanie
LIKE
nie zadziała.LIKE
wyszukuje wartości pasujące dokładnie do podanego wzorca. W tym przypadkuLIKE
zostanie znaleziony tylko tekst „sOmeVal”, a nie „someval”.Praktycznym rozwiązaniem jest użycie
LCASE()
funkcji.LCASE('sOmeVal')
pobiera mały ciąg z twojego tekstu: „someval”. Jeśli użyjesz tej funkcji dla obu stron porównania, zadziała:SELECT * FROM myTable WHERE LCASE(myField) LIKE LCASE('sOmeVal')
Instrukcja porównuje dwa ciągi napisane małymi literami, dzięki czemu „sOmeVal” będzie pasować do każdej innej notacji „someval” (np. „Someval”, „sOMEVAl” itp.).
źródło
LCASE()
w SQL Server (przynajmniej tego nie widzę). Myślę, że ta odpowiedź dotyczy zupełnie innego RDBMS. Zobacz moją odpowiedź, aby uzyskać wyjaśnienie dotyczące porównań ciągów.Możesz wymusić rozróżnianie wielkości liter, rzutując na varbinary w ten sposób:
SELECT * FROM myTable WHERE convert(varbinary, myField) = convert(varbinary, 'sOmeVal')
źródło
W jakiej bazie danych się znajdujesz? W przypadku MS SQL Server jest to ustawienie dotyczące całej bazy danych lub można je zastąpić słowem kluczowym COLLATE dla każdego zapytania.
źródło