SQL para análise de dados · Guias · 30 de outubro de 2026 · 11 min de leitura

LIKE no SQL: curingas % e _, ILIKE, NOT LIKE, acentos e escape

Um painel de partidas em que uma lupa destaca todos os nomes de cidades que começam com as mesmas letras

O LIKE filtra texto por um padrão, e não por um valor exato. O padrão tem dois curingas: % corresponde a qualquer sequência de caracteres, inclusive nenhuma, e _ corresponde a exatamente um caractere. Assim, city LIKE 'Mos%' encontra todas as cidades que começam com “Mos”, model LIKE '%300' encontra os modelos que terminam em “300” e airport_name LIKE '%ovo%' encontra os nomes que contêm “ovo” em qualquer posição. No PostgreSQL e no DuckDB, o LIKE diferencia maiúsculas de minúsculas; o ILIKE é a versão que não diferencia. O NOT LIKE inverte a correspondência, mas nenhum dos dois devolve linhas em que a coluna é NULL.

Os exemplos rodam no banco de dados de uma companhia aérea usado no curso de SQL da Nomto, com sintaxe do PostgreSQL executada no DuckDB (o motor da sala de SQL da Nomto). Os textos dos dados estão em inglês, e cada tabela de resultado saiu da execução real da consulta.

Sintaxe do LIKE

SELECT colunas
FROM tabela
WHERE coluna_de_texto LIKE 'padrão';

O padrão é uma string comum entre aspas simples. Sem curingas, o LIKE se comporta como =; são o % e o _ que o tornam útil. O padrão precisa corresponder ao valor inteiro, e é por isso que a posição do % importa tanto:

padrão significa encontra
'Mos%' começa com “Mos” Moscow
'%sk' termina com “sk” Omsk, Tomsk, Irkutsk
'%ovo%' contém “ovo” Domodedovo, Pulkovo
'_____' exatamente cinco caracteres Kazan, Sochi
'S_r%' S, um caractere qualquer, r, depois qualquer coisa Saratov, Surgut

O curinga %: começa com, termina com, contém

Começa com

SELECT airport_code, airport_name, city
FROM airports
WHERE city LIKE 'Mos%'
ORDER BY airport_code;
airport_code airport_name city
DME Domodedovo Moscow
SVO Sheremetyevo Moscow
VKO Vnukovo Moscow

Termina com

SELECT model
FROM aircrafts
WHERE model LIKE '%300'
ORDER BY model;
model
Boeing 737-300
Boeing 767-300
Boeing 777-300

Contém

% dos dois lados significa “em qualquer lugar da string”:

SELECT airport_name, city
FROM airports
WHERE airport_name LIKE '%ovo%'
ORDER BY airport_name
LIMIT 6;
airport_name city
Domodedovo Moscow
Ivanovo South Ivanovo
Kemerovo Kemerovo
Khomutovo Yuzhno-Sakhalinsk
Khrabrovo Kaliningrad
Koltsovo Yekaterinburg

O resultado completo tem 12 aeroportos; aqui a consulta foi cortada em seis linhas.

O “contém” pega mais do que você talvez queira. Os nomes dos passageiros estão gravados como “NOME SOBRENOME” em maiúsculas. Buscar o sobrenome Ivanov com '%IVANOV%' devolve 14.040 bilhetes, mas '% IVANOV' (um espaço e o sobrenome bem no final) devolve só 7.539:

SELECT CASE WHEN passenger_name LIKE '% IVANOV'  THEN 'IVANOV'
            WHEN passenger_name LIKE '% IVANOVA' THEN 'IVANOVA'
            ELSE 'other' END AS surname,
       COUNT(*) AS tickets
FROM tickets
WHERE passenger_name LIKE '%IVANOV%'
GROUP BY surname
ORDER BY tickets DESC;
surname tickets
IVANOV 7539
IVANOVA 6501

O padrão frouxo pegou, sem avisar, também a forma feminina Ivanova. É o mesmo problema de buscar '%SILVA%' numa base brasileira e trazer junto “SILVANA” e “SILVEIRA”. Ancore o padrão o máximo que os dados permitirem.

O curinga _: exatamente um caractere

O _ vale por um caractere, nem mais nem menos. Cinco sublinhados encontram cidades com cinco letras:

SELECT city
FROM airports
WHERE city LIKE '_____'
ORDER BY city;
city
Anapa
Chita
Kazan
Kirov
Kursk
Kyzyl
Mirny
Nadym
Penza
Pskov
Sochi
Tomsk
Ukhta

Misturando os dois curingas: 'S_r%' significa S, depois um caractere qualquer, depois r, depois qualquer coisa.

SELECT city FROM airports WHERE city LIKE 'S_r%' ORDER BY city;
city
Saransk
Saratov
Strezhevoy
Surgut

Strezhevoy não é erro: S, depois “t” no lugar do sublinhado, depois “r”. O _ aceita qualquer caractere, consoantes inclusive.

Busca sem diferenciar maiúsculas: ILIKE e LOWER

No PostgreSQL e no DuckDB, o LIKE compara os caracteres exatamente, então minúscula não corresponde a maiúscula:

SELECT 'ABC' LIKE 'abc' AS like_result, 'ABC' ILIKE 'abc' AS ilike_result;
like_result ilike_result
false true

WHERE city LIKE 'mos%' não devolve nenhuma linha; WHERE city ILIKE 'mos%' devolve os três aeroportos de Moscou. O ILIKE não é SQL padrão: existe no PostgreSQL, no DuckDB e no Snowflake, mas não no MySQL nem no SQL Server. A forma portável é passar os dois lados para minúsculas:

SELECT city FROM airports WHERE lower(city) LIKE 'mos%';

No MySQL e no SQL Server, a diferenciação de maiúsculas depende da collation da coluna, e as collations padrão não diferenciam, então lá um LIKE 'mos%' simples já encontra Moscow. Essa diferença costuma surpreender quando uma consulta muda de banco.

LIKE e acentos

Em português, o problema seguinte aos maiúsculas são os acentos: quem digita “sao paulo” na busca espera encontrar “São Paulo”. Para o LIKE, “a” e “ã” são caracteres diferentes:

SELECT 'São Paulo' LIKE 'Sao%' AS like_result,
       strip_accents('São Paulo') LIKE 'Sao%' AS sem_acento,
       'SÃO PAULO' ILIKE 'são%' AS ilike_result;
like_result sem_acento ilike_result
false true true

O ILIKE resolve maiúsculas e minúsculas, inclusive de letras acentuadas, mas não ignora o acento. Para isso cada banco tem o seu caminho:

NOT LIKE, e por que as linhas NULL somem

O NOT LIKE mantém as linhas que não correspondem. A armadilha: se a coluna é NULL, tanto LIKE quanto NOT LIKE devolvem NULL, e o WHERE descarta a linha nos dois casos. Cerca de metade dos bilhetes tem um e-mail em contact_data; vamos separá-los pela presença de um sublinhado no endereço (como o \_ funciona é explicado na próxima seção):

SELECT COUNT(*) FILTER (WHERE contact_data->>'email' LIKE '%\_%' ESCAPE '\')     AS with_underscore,
       COUNT(*) FILTER (WHERE contact_data->>'email' NOT LIKE '%\_%' ESCAPE '\') AS without_underscore,
       COUNT(*) FILTER (WHERE contact_data->>'email' IS NULL)                    AS no_email,
       COUNT(*) AS total
FROM tickets;
with_underscore without_underscore no_email total
87828 111255 167650 366733

LIKE mais NOT LIKE dá 199.083, e não 366.733: os 167.650 bilhetes sem e-mail não estão em nenhum dos dois grupos. Se “não corresponde” deve incluir “não tem valor”, diga isso explicitamente: WHERE email NOT LIKE '%\_%' ESCAPE '\' OR email IS NULL, ou WHERE COALESCE(email, '') NOT LIKE .... O guia de NULL no SQL explica a lógica de três valores por trás disso.

Escape: como buscar um % ou _ literal

Como % e _ são curingas, você precisa de um caractere de escape para buscar os próprios caracteres. Sem ele, “e-mails que contêm um sublinhado” corresponde a todos os e-mails:

SELECT COUNT(*) AS emails,
       COUNT(*) FILTER (WHERE email LIKE '%_%')               AS unescaped,
       COUNT(*) FILTER (WHERE email LIKE '%\_%' ESCAPE '\')   AS escaped
FROM (SELECT contact_data->>'email' AS email FROM tickets) t
WHERE email IS NOT NULL;
emails unescaped escaped
199083 199083 87828

'%_%' significa “pelo menos um caractere de qualquer tipo”, o que toda string não vazia satisfaz. Com ESCAPE '\', a sequência \_ passa a significar um sublinhado de verdade. O mesmo vale para o %: para achar descontos como “15%” num texto, use LIKE '%15\%%' ESCAPE '\'.

O caractere de escape padrão muda de banco para banco, e é aqui que as consultas quebram quando são copiadas:

Uma cláusula ESCAPE explícita funciona em todos eles, e você pode escolher qualquer caractere, por exemplo LIKE '%!_%' ESCAPE '!'.

Vários padrões ao mesmo tempo

O LIKE aceita um padrão só. Para vários, combine condições com OR e coloque-as entre parênteses se houver outras condições no WHERE:

SELECT city
FROM airports
WHERE (city LIKE 'Nov%' OR city LIKE 'Nor%')
ORDER BY city;
city
Norilsk
Novokuznetsk
Novosibirsk
Novy Urengoy

Sem os parênteses, WHERE a AND b OR c é lido como (a AND b) OR c, uma fonte clássica de linhas a mais.

O PostgreSQL também aceita city LIKE ANY (ARRAY['Nov%', 'Nor%']). O DuckDB não: ele falha com Unsupported comparison "~~" for ANY/ALL subquery, então na sala de SQL da Nomto use OR.

Quando os padrões ficam complicados, passe para expressões regulares. No DuckDB, regexp_matches(city, '^(Nov|Nor|Noy)') devolve Norilsk, Novokuznetsk, Novosibirsk, Novy Urengoy e Noyabrsk. O PostgreSQL usa o operador city ~ '^(Nov|Nor|Noy)'. Cuidado com o ~ no DuckDB: lá ele exige que a regex corresponda à string inteira, então city ~ '^Nov' não devolve nada e você precisaria de city ~ 'Nov.*'.

LIKE vs =

= LIKE
Corresponde a o valor exato um padrão com % e _
Curingas nenhum (% é um caractere comum) %, _
Velocidade sempre pode usar índice só usa índice com prefixo fixo
Uso típico status = 'Arrived' city LIKE 'Nov%'

Use = sempre que souber o valor completo. Sem curingas, o LIKE dá o mesmo resultado que o = no PostgreSQL e no DuckDB ('abc ' LIKE 'abc' e 'abc ' = 'abc' são ambos falsos). No SQL Server, o = ignora espaços no final, mas o LIKE os leva em conta, então lá 'abc ' = 'abc' é verdadeiro e 'abc' LIKE 'abc ' é falso.

O LIKE também funciona com datas convertidas em texto, CAST(scheduled_departure AS VARCHAR) LIKE '2026-08-01%', e aqui dá os mesmos 568 voos que um intervalo. Prefira o intervalo, scheduled_departure >= '2026-08-01' AND scheduled_departure < '2026-08-02': ele mantém o tipo da coluna, funciona em qualquer banco seja qual for o formato de data em texto (no SQL Server, um CAST de data para texto sem estilo dá algo como Aug 1 2026 12:00AM) e pode usar índice. Mais sobre isso no guia de funções de data no SQL.

Desempenho do LIKE

Numa tabela grande, o jeito como o padrão começa decide a velocidade:

Motores analíticos colunares, como DuckDB, BigQuery ou Snowflake, varrem colunas rapidamente de qualquer forma, então num conjunto de dados do tamanho do curso você não vai notar a diferença. Numa tabela de produção com milhões de linhas no PostgreSQL ou no MySQL, vai.

Erros comuns

Para extrair partes das strings depois de encontrá-las (SPLIT_PART, SUBSTRING, REPLACE), veja o guia de funções de texto no SQL. Os filtros por padrão também estão na cola de SQL.

Perguntas frequentes

O que significa % no LIKE do SQL?

O % corresponde a qualquer sequência de caracteres, inclusive uma vazia. 'Mos%' encontra “Mos”, “Moscow” e qualquer outra coisa que comece com “Mos”. O _ corresponde a exatamente um caractere.

O LIKE diferencia maiúsculas de minúsculas?

No PostgreSQL, no DuckDB e no Oracle, sim. No MySQL e no SQL Server depende da collation, e as collations padrão não diferenciam. Para uma busca sem diferenciar no PostgreSQL ou no DuckDB, use ILIKE, ou lower(col) LIKE 'padrão' em qualquer banco.

Como fazer o LIKE ignorar acentos?

Remova os acentos dos dois lados antes de comparar: strip_accents no DuckDB, a extensão unaccent no PostgreSQL. No MySQL 8 a collation padrão já ignora acentos; no SQL Server, use uma collation _AI, por exemplo COLLATE Latin1_General_CI_AI.

Como escapar um sublinhado ou um sinal de porcentagem no LIKE?

Coloque um caractere de escape antes dele e declare-o com ESCAPE: col LIKE '%\_%' ESCAPE '\' encontra valores com um sublinhado de verdade. PostgreSQL e MySQL usam a barra invertida por padrão; DuckDB e SQL Server não, então a cláusula ESCAPE explícita é a forma portável. O SQL Server também aceita '%[_]%'.

Posso usar LIKE com vários valores?

Não diretamente. Combine condições com OR (city LIKE 'Nov%' OR city LIKE 'Nor%'), use LIKE ANY (ARRAY[...]) no PostgreSQL ou passe para uma expressão regular.

O LIKE é mais lento que o =?

Um LIKE com prefixo fixo pode usar índice e é quase tão rápido quanto o =. Um padrão que começa com % precisa verificar todas as linhas, o que é bem mais lento em tabelas grandes, a menos que você crie um índice de trigramas (PostgreSQL) ou um índice de texto completo.

Outros idiomas: English, Español, Tiếng Việt, 简体中文