Abaixo estão cinco opções para retornar linhas que contêm letras maiúsculas no SQL Server.
Dados de amostra
Suponha que temos uma tabela com os seguintes dados:
SELECT c1 FROM t1;
Resultado:
+----------------+ | c1 | |----------------| | CAFÉ | | Café | | café | | 1café | | eCafé | | James Bond 007 | | JB 007 | | 007 | | NULL | | | | É | | É 123 | | é | | é 123 | | ø | | Ø | +----------------+
Podemos usar os seguintes métodos para retornar as linhas que contêm letras maiúsculas.
Opção 1:Compare com o LOWER()
Cadeia
Podemos usar o
LOWER()
função para comparar o valor original com seu equivalente em minúsculas:SELECT c1 FROM t1
WHERE LOWER(c1) COLLATE Latin1_General_CS_AS <> c1;
Resultado:
+----------------+ | c1 | |----------------| | CAFÉ | | Café | | eCafé | | James Bond 007 | | JB 007 | | É | | É 123 | | Ø | +----------------+
Usando o diferente de (
<>
) (você pode usar alternativamente !=
em vez de <>
se preferir), apenas retornamos as linhas que são diferentes de seus equivalentes em minúsculas. A razão pela qual fazemos isso é porque, se um valor é o mesmo que seu equivalente em minúsculas, então já estava em minúsculas (e não queremos devolvê-lo). Também usamos
COLLATE Latin1_General_CS_AS
para especificar explicitamente um agrupamento que diferencia maiúsculas de minúsculas (e diferencia acentos). Sem isso, você pode obter resultados inesperados, dependendo do agrupamento usado em seu sistema. Opção 2:comparar com os caracteres reais
Outra opção é usar o
LIKE
operador e especifique os caracteres maiúsculos reais que queremos corresponder:SELECT c1 FROM t1
WHERE c1 LIKE '%[ABCDEFGHIJKLMNOPQRSTUVWXYZ]%'
COLLATE Latin1_General_CS_AS;
Resultado:
+----------------+ | c1 | |----------------| | CAFÉ | | Café | | eCafé | | James Bond 007 | | JB 007 | +----------------+
Nesse caso, menos linhas são retornadas do que no exemplo anterior. Isso ocorre porque não especifiquei caracteres como
É
e Ø
, que foram retornados no exemplo anterior. Nosso resultado contém É
mas essa linha só foi retornada porque também contém outros caracteres maiúsculos que fazem partida. Portanto, essa opção é mais limitada que a anterior, mas fornece mais controle sobre os caracteres que você deseja corresponder.
Opção 3:comparar com um intervalo de caracteres
Alternativamente, podemos especificar o intervalo de caracteres que queremos corresponder:
SELECT * FROM t1
WHERE c1 LIKE '%[A-Z]%'
COLLATE Latin1_General_100_BIN2;
Resultado:
+----------------+ | c1 | |----------------| | CAFÉ | | Café | | eCafé | | James Bond 007 | | JB 007 | +----------------+
Nesse caso, usei um agrupamento binário (
Latin1_General_100_BIN2
). Eu fiz isso porque os agrupamentos binários classificam cada caso separadamente (assim:AB....YZ...ab...yz
). Outros agrupamentos tendem a misturar as letras maiúsculas e minúsculas (assim:
AaBb...YyZz
), que, portanto, corresponderia a caracteres maiúsculos e minúsculos. Opção 4:encontre a primeira instância de um caractere maiúsculo
Outra maneira de fazer isso é usar o
PATINDEX()
função:SELECT * FROM t1
WHERE PATINDEX('%[ABCDEFGHIJKLMNOPQRSTUVWXYZ]%', c1
COLLATE Latin1_General_CS_AS) > 0;
Resultado:
+----------------+ | c1 | |----------------| | CAFÉ | | Café | | eCafé | | James Bond 007 | | JB 007 | +----------------+
Neste exemplo, especificamos os caracteres exatos que queremos corresponder e, portanto, não obtivemos as linhas com os caracteres like
É
e Ø
(diferente daquele que também contém outros caracteres que foram correspondidos). Um benefício desta técnica é que podemos usá-la para ignorar o primeiro caractere (ou número especificado de caracteres) se assim o desejarmos:
SELECT * FROM t1
WHERE PATINDEX('%[ABCDEFGHIJKLMNOPQRSTUVWXYZ]%', c1
COLLATE Latin1_General_CS_AS) > 1;
Resultado:
Time: 0.472s +-------+ | c1 | |-------| | eCafé | +-------+
Portanto, podemos retornar todas as linhas que contêm caracteres maiúsculos, mas onde o primeiro caractere não é maiúsculo.
Isso ocorre porque
PATINDEX()
retorna a posição inicial da primeira ocorrência do padrão (no nosso caso, o padrão é uma lista de caracteres maiúsculos). Se a posição inicial da primeira ocorrência for maior que 1, o primeiro caractere não estará em nossa lista de caracteres maiúsculos. Opção 5:encontrar a primeira instância com base em um intervalo
Também podemos usar
PATINDEX()
com um intervalo:SELECT * FROM t1
WHERE PATINDEX('%[A-Z]%', c1
COLLATE Latin1_General_100_BIN2) > 1;
Resultado:
+-------+ | c1 | |-------| | eCafé | +-------+
Eu novamente usei um agrupamento binário (como no outro exemplo de intervalo).