sql >> Databasteknik >  >> RDS >> Sqlserver

5 sätt att returnera rader som innehåller små bokstäver i SQL Server

Om du behöver hitta rader som innehåller gemener i SQL Server kan du prova något av följande alternativ.

Exempeldata

Anta att vi har en tabell med följande data:

SELECT c1 FROM t1;

Resultat:

+----------------+
| c1             |
|----------------|
| CAFÉ           |
| Café           |
| café           |
| 1café          |
| eCafé          |
| James Bond 007 |
| JB 007         |
| 007            |
| NULL           |
|                |
| É              |
| É 123          |
| é              |
| é 123          |
| ø              |
| Ø              |
+----------------+

Vi kan använda följande metoder för att returnera de rader som innehåller gemener.

Alternativ 1:Jämför med UPPER() Sträng

Vi kan använda UPPER() funktion för att jämföra det ursprungliga värdet med dess motsvarighet i versaler:

SELECT * FROM t1
WHERE UPPER(c1) COLLATE Latin1_General_CS_AS <> c1;

Resultat:

+----------------+
| c1             |
|----------------|
| Café           |
| café           |
| 1café          |
| eCafé          |
| James Bond 007 |
| é              |
| é 123          |
| ø              |
+----------------+

Genom att använda inte lika med (<> ) operator (du kan alternativt använda != istället för <> om du föredrar det), returnerar vi bara de rader som skiljer sig från sina versaler. Anledningen till att vi gör detta är att om ett värde är detsamma som dess versaler, så var det redan versaler till att börja med (och vi vill inte returnera det).

Vi använder också COLLATE Latin1_General_CS_AS för att uttryckligen ange en skiftlägeskänslig (och accentkänslig) sammanställning. Utan detta kan du få oväntade resultat, beroende på vilken sortering som används på ditt system.

Alternativ 2:Jämför med de faktiska tecknen

Vi kan alternativt använda LIKE operatorn och ange de faktiska gemener som vi vill matcha:

SELECT * FROM t1
WHERE c1 LIKE '%[abcdefghijklmnopqrstuvwxyz]%'
COLLATE Latin1_General_CS_AS;

Resultat:

+----------------+
| c1             |
|----------------|
| Café           |
| café           |
| 1café          |
| eCafé          |
| James Bond 007 |
+----------------+

I det här fallet returneras färre rader än i föregående exempel. Detta beror på att jag inte angav tecken som é och ø , som returnerades i föregående exempel. Även om en rad innehåller é , returnerades den raden bara eftersom den också innehåller andra gemener som matchar.

Därför är det här exemplet mer begränsat än det föregående, men det ger dig mer kontroll över de karaktärer du vill matcha.

Alternativ 3:Jämför med en rad tecken

Vi kan alternativt specificera intervallet av tecken vi vill matcha:

SELECT * FROM t1
WHERE c1 LIKE '%[a-z]%'
COLLATE Latin1_General_100_BIN2;

Resultat:

+----------------+
| c1             |
|----------------|
| Café           |
| café           |
| 1café          |
| eCafé          |
| James Bond 007 |
+----------------+

I det här fallet använde jag en binär sortering (Latin1_General_100_BIN2 ). Jag gjorde detta eftersom binära sammanställningar sorterar varje fall separat (så här:AB....YZ...ab...yz ).

Andra sorteringar tenderar att blanda versaler och gemener (så här:AaBb...YyZz ), som därför skulle matcha både versaler och gemener.

Alternativ 4:Hitta den första instansen av ett gement tecken

Ett annat sätt att göra det är att använda PATINDEX() funktion:

SELECT * FROM t1
WHERE PATINDEX('%[abcdefghijklmnopqrstuvwxyz]%', c1
COLLATE Latin1_General_CS_AS) > 0;

Resultat:

+----------------+
| c1             |
|----------------|
| Café           |
| café           |
| 1café          |
| eCafé          |
| James Bond 007 |
+----------------+

I det här exemplet anger vi de exakta tecken som vi vill matcha, så i det här fallet fick vi inte raderna med tecken som é och ø (annat än den som också innehåller andra tecken som matchades).

En fördel med denna teknik är att vi kan använda den för att ignorera det första tecknet (eller specificerat antal tecken) om vi så önskar:

SELECT * FROM t1
WHERE PATINDEX('%[abcdefghijklmnopqrstuvwxyz]%', c1
COLLATE Latin1_General_CS_AS) > 1;

Resultat:

+----------------+
| c1             |
|----------------|
| Café           |
| 1café          |
| James Bond 007 |
+----------------+

Därför kan vi returnera alla rader som innehåller gemener, men där det första tecknet inte är gemener.

Detta beror på att PATINDEX() returnerar startpositionen för den första förekomsten av mönstret (i vårt fall är mönstret en lista med gemener). Om startpositionen för den första förekomsten är större än 1, så finns inte det första tecknet i vår lista över gemener.

Även om den här tekniken kan användas för att ignorera att det första tecknet är versaler, utesluter det inte att det första tecknet kan vara ett annat tecken, till exempel ett nummer. Vi kan se detta i den andra raden, som innehåller 1café .

Alternativ 5:Hitta den första instansen baserat på ett intervall

Vi kan också använda PATINDEX() med ett intervall:

SELECT * FROM t1
WHERE PATINDEX('%[a-z]%', c1
COLLATE Latin1_General_100_BIN2) > 1;

Resultat:

+----------------+
| c1             |
|----------------|
| Café           |
| 1café          |
| James Bond 007 |
+----------------+

Jag använde återigen en binär sammanställning (som med det andra exemplet med intervall).


  1. PostgreSQL 8.4 ger DML-privilegier på alla tabeller till en roll

  2. Filtrera data med JDBC RowSet

  3. ClusterControl:Introduktion till New Query Monitor

  4. Hur man använder Oracle PLSQL-tabeller (associativ array eller index-för-tabell)