Come faccio a costruire una query SQL (MS SQL Server) in cui la clausola "where" non fa distinzione tra maiuscole e minuscole?
SELECT * FROM myTable WHERE myField = 'sOmeVal'
Voglio che i risultati tornino ignorando il caso
Come faccio a costruire una query SQL (MS SQL Server) in cui la clausola "where" non fa distinzione tra maiuscole e minuscole?
SELECT * FROM myTable WHERE myField = 'sOmeVal'
Voglio che i risultati tornino ignorando il caso
Risposte:
Nella configurazione predefinita di un database di SQL Server, i confronti tra stringhe non fanno distinzione tra maiuscole e minuscole. Se il database sostituisce questa impostazione (tramite l'uso di regole di confronto alternative), sarà necessario specificare il tipo di regole di confronto da utilizzare nella query.
SELECT * FROM myTable WHERE myField = 'sOmeVal' COLLATE SQL_Latin1_General_CP1_CI_AS
Nota che le regole di confronto che ho fornito sono solo un esempio (anche se molto probabilmente funzionerà bene per te). Una descrizione più completa delle regole di confronto di SQL Server è disponibile qui .
UPPER
o LOWER
caso quindi utilizzando il LIKE
per cercare?
Di solito, i confronti tra stringhe non fanno distinzione tra maiuscole e minuscole. Se il database è configurato per le regole di confronto con distinzione tra maiuscole e minuscole, è necessario forzarne l'uso senza distinzione tra maiuscole e minuscole:
SELECT balance FROM people WHERE email = 'billg@microsoft.com'
COLLATE SQL_Latin1_General_CP1_CI_AS
Ho trovato un'altra soluzione altrove; cioè da usare
upper(@yourString)
ma tutti qui dicono che, in SQL Server, non importa perché ignora comunque il caso? Sono abbastanza sicuro che il nostro database fa distinzione tra maiuscole e minuscole.
Le prime 2 risposte (da Adam Robinson e Andrejs Cainikovs ) sono un po 'corrette, in quanto tecnicamente funzionano, ma le loro spiegazioni sono sbagliate e quindi potrebbero essere fuorvianti in molti casi. Ad esempio, sebbene le SQL_Latin1_General_CP1_CI_AS
regole di confronto funzionino in molti casi, non si dovrebbe presumere che siano le regole di confronto appropriate senza distinzione tra maiuscole e minuscole. Infatti, dato che l'OP sta lavorando in un database con un confronto case-sensitive (o possibilmente binario), sappiamo che l'OP non sta usando il confronto che è l'impostazione predefinita per così tante installazioni (specialmente quelle installate su un sistema operativo usando gli Stati Uniti l'inglese come lingua): SQL_Latin1_General_CP1_CI_AS
. Certo, l'OP potrebbe essere utilizzato SQL_Latin1_General_CP1_CS_AS
, ma quando si lavora conVARCHAR
data, è importante non modificare la code page in quanto potrebbe portare alla perdita di dati, e ciò è controllato dalle impostazioni locali / cultura delle regole di confronto (ad esempio Latin1_General vs French vs Hebrew ecc). Si prega di vedere il punto 9 di seguito.
Le altre quattro risposte sono sbagliate a vari livelli.
Chiarirò qui tutti i malintesi in modo che i lettori possano, si spera, fare le scelte più appropriate / efficienti.
Non utilizzare UPPER()
. Questo è un lavoro extra completamente inutile. Usa una COLLATE
clausola. In entrambi i casi è necessario eseguire un confronto tra stringhe, ma using UPPER()
deve anche controllare, carattere per carattere, se è presente una mappatura maiuscola, quindi modificarla. E devi farlo su entrambi i lati. L'aggiunta COLLATE
indica semplicemente all'elaborazione di generare le chiavi di ordinamento utilizzando un insieme di regole diverso da quello predefinito. L'uso COLLATE
è decisamente più efficiente (o "performante", se ti piace quella parola :) che usare UPPER()
, come dimostrato in questo script di test (su PasteBin) .
C'è anche il problema notato da @Ceisc sulla risposta di @ Danny:
In alcune lingue, le conversioni dei casi non vengono eseguite in andata e ritorno. cioè LOWER (x)! = LOWER (UPPER (x)).
La lettera maiuscola turca "İ" è l'esempio comune.
No, le regole di confronto non sono un'impostazione a livello di database, almeno non in questo contesto. Esistono regole di confronto predefinite a livello di database e vengono utilizzate come impostazioni predefinite per le colonne modificate e di nuova creazione che non specificano la COLLATE
clausola (che è probabile da cui provenga questo malinteso comune), ma non influisce direttamente sulle query a meno che tu non lo sia confrontando i valori letterali e le variabili stringa con altri valori letterali e variabili stringa oppure si fa riferimento a metadati a livello di database.
No, le regole di confronto non sono per query.
Le regole di confronto sono per predicato (cioè qualcosa di operando qualcosa) o espressione, non per query. E questo è vero per l'intera query, non solo per la WHERE
clausola. Questo copre JOINs, GROUP BY, ORDER BY, PARTITION BY, ecc.
No, non convertire in VARBINARY
(ad es. convert(varbinary, myField) = convert(varbinary, 'sOmeVal')
) Per i seguenti motivi:
_BIN2
se stai usando SQL Server 2008 o più recente, altrimenti non hai altra scelta che usarne uno che finisca con _BIN
. Se i dati sono NVARCHAR
, non importa quale locale usi poiché sono tutti uguali in quel caso, quindi Latin1_General_100_BIN2
funziona sempre. Se i dati sono VARCHAR
, è necessario utilizzare la stessa impostazione internazionale che i dati sono attualmente in (ad esempio Latin1_General
, French
, Japanese_XJIS
, ecc), perché l'impostazione internazionale determina la pagina di codice che viene utilizzato, e la modifica di pagine di codice in grado di alterare i dati (ad esempio perdita di dati).CONVERT()
esso, utilizzerà il valore predefinito 30. Il pericolo è che, se la stringa può superare i 30 byte, verrà troncata silenziosamente e probabilmente otterrai risultati errati da questo predicato.No, LIKE
non fa sempre distinzione tra maiuscole e minuscole. Utilizza le regole di confronto della colonna a cui si fa riferimento o le regole di confronto del database se una variabile viene confrontata con un valore letterale stringa o le regole di confronto specificate tramite la COLLATE
clausola facoltativa .
LCASE
non è una funzione di SQL Server. Sembra essere Oracle o MySQL. O forse Visual Basic?
Poiché il contesto della domanda sta confrontando una colonna con una stringa letterale, né il confronto dell'istanza (spesso denominato "server") né il confronto del database hanno alcun impatto diretto qui. Le regole di confronto vengono archiviate per ogni colonna e ogni colonna può avere regole di confronto diverse e non è necessario che tali regole di confronto siano le stesse delle regole di confronto predefinite del database o dell'istanza. Certo, le regole di confronto dell'istanza sono l'impostazione predefinita per ciò che un database appena creato utilizzerà come regole di confronto predefinite se la COLLATE
clausola non è stata specificata durante la creazione del database. Allo stesso modo, le regole di confronto predefinite del database sono ciò che una colonna modificata o appena creata utilizzerà se la COLLATE
clausola non è stata specificata.
È necessario utilizzare le regole di confronto senza distinzione tra maiuscole e minuscole, altrimenti le stesse delle regole di confronto della colonna. Utilizzare la seguente query per trovare le regole di confronto della colonna (modificare il nome della tabella e il nome dello schema):
SELECT col.*
FROM sys.columns col
WHERE col.[object_id] = OBJECT_ID(N'dbo.TableName')
AND col.[collation_name] IS NOT NULL;
Quindi cambia semplicemente _CS
essere _CI
. Quindi, Latin1_General_100_CS_AS
sarebbe diventato Latin1_General_100_CI_AS
.
Se la colonna utilizza un confronto binario (che termina con _BIN
o _BIN2
), trova un confronto simile utilizzando la query seguente:
SELECT *
FROM sys.fn_helpcollations() col
WHERE col.[name] LIKE N'{CurrentCollationMinus"_BIN"}[_]CI[_]%';
Ad esempio, supponendo che la colonna stia usando Japanese_XJIS_100_BIN2
, fai questo:
SELECT *
FROM sys.fn_helpcollations() col
WHERE col.[name] LIKE N'Japanese_XJIS_100[_]CI[_]%';
Per maggiori informazioni su regole di confronto, codifiche, ecc., Visitare: Informazioni sulle collazioni
No, solo l'utilizzo LIKE
non funzionerà. LIKE
cerca i valori che corrispondono esattamente al modello fornito. In questo caso LIKE
troverà solo il testo "sOmeVal" e non "someval".
Una soluzione pratica è usare la LCASE()
funzione. LCASE('sOmeVal')
ottiene la stringa minuscola del testo: 'someval'. Se utilizzi questa funzione per entrambi i lati del confronto, funziona:
SELECT * FROM myTable WHERE LCASE(myField) LIKE LCASE('sOmeVal')
L'istruzione confronta due stringhe minuscole, in modo che 'sOmeVal' corrisponda a ogni altra notazione di 'someval' (ad esempio 'Someval', 'sOMEVAl' ecc.).
LCASE()
in SQL Server (almeno non che io possa vedere). Penso che questa risposta sia per un RDBMS completamente diverso. Si prega di consultare la mia risposta per chiarimenti sui confronti di stringhe.
Puoi forzare la distinzione tra maiuscole e minuscole, eseguendo il casting su un varbinary in questo modo:
SELECT * FROM myTable
WHERE convert(varbinary, myField) = convert(varbinary, 'sOmeVal')
Su quale database ti trovi? Con MS SQL Server, è un'impostazione a livello di database oppure puoi sovrascriverla per query con la parola chiave COLLATE.
WHERE
dichiarazione, e influenzerà tutte leWHERE
clausole, giusto?