Il server SQL ignora il caso in un'espressione where
-
11-07-2019 - |
Domanda
Come si costruisce una query SQL (MS SQL Server) in cui " dove " la clausola non fa distinzione tra maiuscole e minuscole?
SELECT * FROM myTable WHERE myField = 'sOmeVal'
Voglio che i risultati ritornino ignorando il caso
Soluzione
Nella configurazione predefinita di un database SQL Server, i confronti di stringhe non fanno distinzione tra maiuscole e minuscole. Se il tuo database sovrascrive questa impostazione (tramite l'uso di un confronto alternativo), dovrai specificare quale tipo di confronto utilizzare nella query.
SELECT * FROM myTable WHERE myField = 'sOmeVal' COLLATE SQL_Latin1_General_CP1_CI_AS
Nota che la collazione che ho fornito è solo un esempio (anche se molto probabilmente funzionerà bene per te). Una descrizione più completa delle regole di confronto di SQL Server è disponibile qui .
Altri suggerimenti
Di solito, i confronti tra stringhe non fanno distinzione tra maiuscole e minuscole. Se il database è configurato per regole di confronto con distinzione tra maiuscole e minuscole, è necessario forzare l'uso di una 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è, per 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 sia sensibile al maiuscolo / minuscolo.
No, usare solo LIKE
non funzionerà. LIKE
cerca valori che corrispondono esattamente al modello dato. In questo caso LIKE
troverà solo il testo 'sOmeVal' e non 'someval'.
Una soluzione pratica sta usando la funzione LCASE ()
. LCASE ('sOmeVal')
ottiene la stringa minuscola del testo: 'someval'. Se usi questa funzione per entrambi i lati del tuo confronto, funziona:
SELEZIONA * DA myTable DOVE LCASE (myField) COME LIKE LCASE ('sOmeVal')
L'istruzione confronta due stringhe minuscole, in modo che il tuo "sOmeVal" corrisponderà a ogni altra notazione di "someval" (ad esempio "Someval", "sOMEVAl" ecc.).
Le prime 2 risposte (da Adam Robinson e Andrejs Cainikovs ) sono piuttosto corretti, dal momento che funzionano tecnicamente, ma le loro spiegazioni sono sbagliate e quindi potrebbero essere fuorvianti in molti casi. Ad esempio, mentre le regole di confronto SQL_Latin1_General_CP1_CI_AS
funzioneranno in molti casi, non si deve supporre che siano le regole di confronto senza distinzione tra maiuscole e minuscole appropriate. Infatti, dato che l'OP sta funzionando in un database con regole di confronto sensibili al maiuscolo / minuscolo (o forse binario), sappiamo che l'OP non utilizza le regole di confronto predefinite per così tante installazioni (specialmente quelle installate su un sistema operativo usando l'inglese americano come lingua): SQL_Latin1_General_CP1_CI_AS
. Certo, l'OP potrebbe utilizzare SQL_Latin1_General_CP1_CS_AS
, ma quando si lavora con i dati VARCHAR
, è importante non modificare la tabella codici in quanto potrebbe condurre alla perdita di dati, e ciò è controllato dalla locale / cultura della collazione (cioè Latin1_General vs French vs Hebrew ecc.). Si prega di consultare il punto 9 di seguito.
Le altre quattro risposte sono errate in varia misura.
Chiarirò qui tutti i malintesi in modo che i lettori possano sperare di fare le scelte più appropriate / efficienti.
-
Non utilizzare
UPPER ()
. Questo è un lavoro extra completamente inutile. Usa una clausolaCOLLATE
. In entrambi i casi è necessario eseguire un confronto tra stringhe, ma l'utilizzo diUPPER ()
deve anche controllare, carattere per carattere, per vedere se esiste una mappatura maiuscola e quindi modificarlo. E devi farlo da entrambe le parti. L'aggiunta diCOLLATE
indica semplicemente all'elaborazione di generare le chiavi di ordinamento utilizzando un set di regole diverso da quello predefinito. L'uso diCOLLATE
è decisamente più efficiente (o "performante", se ti piace quella parola :) rispetto all'utilizzo diUPPER ()
, come dimostrato in questo script di test (su PasteBin) .Esiste anche il problema segnalato da @Ceisc su @ La risposta di Danny:
In alcune lingue le conversioni dei casi non vanno di andata e ritorno. cioè INFERIORE (x)! = INFERIORE (SUPERIORE (x)).
La maiuscola turca " I " è l'esempio comune.
-
No, le regole di confronto non sono impostazioni a livello di database, almeno non in questo contesto. Esiste un confronto predefinito a livello di database e viene utilizzato come predefinito per le colonne modificate e di nuova creazione che non specificano la clausola
COLLATE
(che è probabilmente la fonte di questo malinteso comune), ma non influisce direttamente sulle query, a meno che non si stiano confrontando valori letterali e variabili di stringa con valori letterali e variabili di altre stringhe o facendo riferimento a metadati a livello di database. -
No, le regole di confronto non sono per query.
-
Le regole di confronto sono per predicato (ovvero qualcosa di operando qualcosa) o espressione, non per query. E questo vale per l'intera query, non solo per la clausola
WHERE
. Questo riguarda JOIN, GROUP BY, ORDER BY, PARTITION BY, ecc. -
No, non convertire in
VARBINARY
(ad es.convert (varbinary, myField) = convert (varbinary, 'sOmeVal')
) per i seguenti motivi:- questo è un confronto binario, che non fa distinzione tra maiuscole e minuscole (che è ciò che questa domanda chiede)
- se si desidera un confronto binario, utilizzare un confronto binario. Utilizzare uno che termina con
_BIN2
se si utilizza SQL Server 2008 o versione successiva, altrimenti non si ha altra scelta che utilizzare quello che termina con_BIN
. Se i dati sonoNVARCHAR
, non importa quale locale usi a
Puoi forzare la distinzione tra maiuscole e minuscole, eseguendo il casting su un varbinary del genere:
SELECT * FROM myTable
WHERE convert(varbinary, myField) = convert(varbinary, 'sOmeVal')
Su quale database sei? Con MS SQL Server, è un'impostazione a livello di database, oppure puoi sovrascriverla per query con la parola chiave COLLATE.