Ao usar o SQL, existem benefícios em usar =
uma WHERE
cláusula em vez de LIKE
?
Sem operadores especiais, LIKE
e =
são os mesmos, certo?
5
votos para a tag de operador like . Posso pedir que você sugira sql-like como sinônimo ?
Ao usar o SQL, existem benefícios em usar =
uma WHERE
cláusula em vez de LIKE
?
Sem operadores especiais, LIKE
e =
são os mesmos, certo?
5
votos para a tag de operador like . Posso pedir que você sugira sql-like como sinônimo ?
Respostas:
LIKE
e =
são operadores diferentes. A maioria das respostas aqui se concentra no suporte a caracteres curinga, que não é a única diferença entre esses operadores!
=
é um operador de comparação que opera em números e seqüências de caracteres. Ao comparar cadeias, o operador de comparação compara cadeias inteiras .
LIKE
é um operador de cadeia que compara caractere por caractere .
Para complicar, os dois operadores usam um agrupamento que pode ter efeitos importantes no resultado da comparação.
Vamos primeiro identificar um exemplo em que esses operadores produzem resultados obviamente diferentes. Permita-me citar o manual do MySQL:
De acordo com o padrão SQL, o LIKE executa a correspondência por caractere, portanto, pode produzir resultados diferentes do operador = comparação:
mysql> SELECT 'ä' LIKE 'ae' COLLATE latin1_german2_ci;
+-----------------------------------------+
| 'ä' LIKE 'ae' COLLATE latin1_german2_ci |
+-----------------------------------------+
| 0 |
+-----------------------------------------+
mysql> SELECT 'ä' = 'ae' COLLATE latin1_german2_ci;
+--------------------------------------+
| 'ä' = 'ae' COLLATE latin1_german2_ci |
+--------------------------------------+
| 1 |
+--------------------------------------+
Por favor note que esta página do manual do MySQL se chama String Comparison Functions , e =
não é discutida, o que implica que =
não é estritamente uma função de comparação de strings.
=
funciona?O padrão 8.2 do SQL descreve como =
compara cadeias:
A comparação de duas cadeias de caracteres é determinada da seguinte maneira:
a) Se o comprimento em caracteres de X não for igual ao comprimento em caracteres de Y, a sequência mais curta será efetivamente substituída, para fins de comparação, por uma cópia de si mesma que foi estendida para o comprimento da sequência mais longa por concatenação à direita de um ou mais caracteres do bloco, em que o caractere do bloco é escolhido com base no CS. Se CS tiver o atributo NO PAD, o caractere de preenchimento será um caractere dependente de implementação diferente de qualquer caractere no conjunto de caracteres de X e Y que agrupe menos do que qualquer sequência de caracteres em CS. Caso contrário, o caractere de bloco é a.
b) O resultado da comparação de X e Y é dado pela sequência de ordenação CS.
c) Dependendo da sequência de ordenação, duas cadeias podem ser comparadas como iguais, mesmo que tenham comprimentos diferentes ou contenham sequências diferentes de caracteres. Quando as operações MAX, MIN, DISTINCT, referenciam uma coluna de agrupamento e os operadores UNION, EXCEPT e INTERSECT se referem a cadeias de caracteres, o valor específico selecionado por essas operações em um conjunto de valores iguais depende da implementação.
(Enfase adicionada.)
O que isto significa? Isso significa que, ao comparar seqüências de caracteres, o =
operador é apenas um invólucro fino em torno do agrupamento atual. Um agrupamento é uma biblioteca que possui várias regras para comparar seqüências de caracteres. Aqui está um exemplo de agrupamento binário do MySQL :
static int my_strnncoll_binary(const CHARSET_INFO *cs __attribute__((unused)),
const uchar *s, size_t slen,
const uchar *t, size_t tlen,
my_bool t_is_prefix)
{
size_t len= MY_MIN(slen,tlen);
int cmp= memcmp(s,t,len);
return cmp ? cmp : (int)((t_is_prefix ? len : slen) - tlen);
}
Esse agrupamento em particular compara byte a byte (e é por isso que é chamado de "binário" - não dá nenhum significado especial às strings). Outros agrupamentos podem fornecer comparações mais avançadas.
Por exemplo, aqui está um agrupamento UTF-8 que suporta comparações que não diferenciam maiúsculas de minúsculas. O código é muito longo para colar aqui, mas vá para esse link e leia o corpo de my_strnncollsp_utf8mb4()
. Esse agrupamento pode processar vários bytes por vez e aplicar várias transformações (como comparação sem distinção entre maiúsculas e minúsculas). O =
operador é completamente abstraído dos caprichos do agrupamento.
LIKE
funciona?O SQL Standard § 8.5 descreve como se LIKE
comparam as strings:
O <predicado>
M LIKE P
é verdadeiro se existir um particionamento de M em substrings, de modo que:
i) Uma substring de M é uma sequência de 0 ou mais <representação de caractere> s contígua de M e cada <representação de caractere> de M faz parte de exatamente uma substring.
ii) Se o i-ésimo especificador de substring de P for um especificador arbitrário de caracteres, o i-ésimo substring de M será qualquer <representação de caractere> única.
iii) Se o i-ésimo especificador de substring de P for um especificador de string arbitrário, o i-ésimo substring de M será qualquer sequência de 0 ou mais <representação de caractere> s.
iv) Se o i-ésimo especificador de substring de P não for um especificador arbitrário de caracteres nem um especificador de string arbitrário, o i-ésimo substring de M será igual a esse especificador de substring, de acordo com a sequência de intercalação do <like predicate>, sem o acréscimo de caracteres <space> a M e tem o mesmo comprimento que o especificador de substring.
v) O número de substrings de M é igual ao número de especificadores de substring de P.
(Enfase adicionada.)
Isso é bastante prolixo, então vamos detalhar. Os itens ii e iii se referem aos caracteres curinga _
e %
, respectivamente. Se P
não contiver curingas, apenas o item iv será aplicado. Este é o caso de interesse apresentado pelo OP.
Nesse caso, ele compara cada "substring" (caracteres individuais) M
com cada substring P
usando o agrupamento atual.
A linha inferior é que, ao comparar cadeias, =
compara a cadeia inteira enquanto LIKE
compara um caractere de cada vez. Ambas as comparações usam o agrupamento atual. Essa diferença leva a resultados diferentes em alguns casos, como evidenciado no primeiro exemplo neste post.
Qual deles você deve usar? Ninguém pode lhe dizer isso - você precisa usar o correto para o seu caso de uso. Não otimize prematuramente alternando operadores de comparação.
LIKE
faz, mas essa resposta explica incrivelmente que usar LIKE
sem %
ou _
presente não é o mesmo que usar =
. Que sua resposta receba mil votos positivos.
'AbCdEfG'
, e eu faço WHERE MyCol = 'abcdefg'
, eu ainda obter essa fileira traseira, embora sejam claramente não byte a byte equivalente
set charset latin1;
SELECT 'ä' = 'ae' COLLATE latin1_german2_ci;
dá 0 e SELECT 'ä' LIKE 'ae' COLLATE latin1_german2_ci;
também 0.
O operador equals (=) é um "operador de comparação compara dois valores para igualdade". Em outras palavras, em uma instrução SQL, ela não retornará true, a menos que ambos os lados da equação sejam iguais. Por exemplo:
SELECT * FROM Store WHERE Quantity = 200;
O operador LIKE "implementa uma comparação de correspondência de padrões" que tenta corresponder "a um valor de sequência em relação a uma sequência de caracteres contendo caracteres curinga". Por exemplo:
SELECT * FROM Employees WHERE Name LIKE 'Chris%';
LIKE geralmente é usado apenas com strings e iguais (acredito) é mais rápido. O operador equals trata caracteres curinga como caracteres literais. A diferença nos resultados retornados é a seguinte:
SELECT * FROM Employees WHERE Name = 'Chris';
E
SELECT * FROM Employees WHERE Name LIKE 'Chris';
Retornaria o mesmo resultado, embora o uso de LIKE geralmente levasse mais tempo, pois é uma correspondência de padrão. Contudo,
SELECT * FROM Employees WHERE Name = 'Chris%';
E
SELECT * FROM Employees WHERE Name LIKE 'Chris%';
Retornaria resultados diferentes, onde o uso de "=" resulta apenas em resultados com "Chris%" sendo retornados e o operador LIKE retornará qualquer coisa que comece com "Chris".
Espero que ajude. Algumas boas informações podem ser encontradas aqui .
Esta é uma cópia / pasta de outra resposta minha para a pergunta SQL 'like' vs '=' performance :
Um exemplo pessoal usando o mysql 5.5: eu tive uma junção interna entre 2 tabelas, uma de 3 milhões de linhas e uma de 10 mil linhas.
Ao usar um like em um índice como abaixo (sem curingas), demorou cerca de 30 segundos:
where login like '12345678'
usando 'explicar' eu recebo:
Ao usar um '=' na mesma consulta, demorou cerca de 0,1 segundos:
where login ='12345678'
Usando 'explicar' eu recebo:
Como você pode ver, a like
busca do índice foi completamente cancelada, portanto, a consulta levou 300 vezes mais tempo.
LIKE
e =
são diferentes. LIKE
é o que você usaria em uma consulta de pesquisa. Também permite curingas como _
(curinga de caractere simples) e %
(curinga de vários caracteres).
=
deve ser usado se você quiser correspondências exatas e será mais rápido.
Depende do sistema de banco de dados.
Geralmente sem caracteres especiais, sim, = e LIKE são iguais.
Alguns sistemas de banco de dados, no entanto, podem tratar as configurações de agrupamento de maneira diferente com os diferentes operadores.
Por exemplo, no MySQL as comparações com = on strings sempre diferenciam maiúsculas de minúsculas por padrão, então LIKE sem caracteres especiais é o mesmo. Em alguns outros RDBMS, LIKE não diferencia maiúsculas de minúsculas, enquanto = não é.
Para este exemplo, assumimos que o varcharcol não contém ''
e não possui célula vazia nessa coluna
select * from some_table where varcharCol = ''
select * from some_table where varcharCol like ''
O primeiro resulta na saída de 0 linhas, enquanto o segundo mostra a lista inteira. = é estritamente compatível com maiúsculas e minúsculas, enquanto o tipo age como um filtro. se o filtro não tiver critérios, todos os dados serão válidos.
like - em virtude de sua finalidade, funciona um pouco mais devagar e se destina ao uso com varchar e dados semelhantes.
Se você procurar uma correspondência exata, poderá usar ambos, = e LIKE.
Usar "=" é um pouquinho mais rápido nesse caso (procurando uma correspondência exata) - você mesmo pode verificar isso fazendo a mesma consulta duas vezes no SQL Server Management Studio, uma vez usando "=", uma vez usando "LIKE" e depois, usando a opção "Consulta" / "Incluir plano de execução real".
Execute as duas consultas e você verá os resultados duas vezes, além dos dois planos de execução reais. No meu caso, eles foram divididos em 50% vs. 50%, mas o plano de execução "=" tem um "custo estimado de subárvore" menor (exibido quando você passa o mouse sobre a caixa "SELECT" mais à esquerda) - mas, novamente, é realmente não é uma diferença enorme.
Mas quando você começa a procurar com curingas na sua expressão LIKE, o desempenho da pesquisa diminui. A pesquisa "LIKE Mill%" ainda pode ser bastante rápida - o SQL Server pode usar um índice nessa coluna, se houver. A pesquisa "LIKE% expression%" é terrivelmente lenta, pois a única maneira de o SQL Server satisfazer essa pesquisa é fazendo uma verificação completa da tabela. Portanto, tenha cuidado com o seu gosto!
Marc
Usar = evita caracteres curinga e conflitos de caracteres especiais na cadeia quando você cria a consulta em tempo de execução.
Isso facilita a vida do programador por não ter que escapar de todos os caracteres curinga especiais que podem aparecer na cláusula LIKE e por não produzir o resultado pretendido. Afinal, = é o cenário de caso de uso de 99%, seria uma dor ter que escapar deles sempre.
revira os olhos nos anos 90
Também suspeito que seja um pouco mais lento, mas duvido que seja significativo se não houver curingas no padrão.
Para abordar a questão original sobre desempenho, ela se resume à utilização do índice . Quando ocorre uma simples varredura de tabela, "LIKE" e "=" são idênticos . Quando os índices estão envolvidos, isso depende de como a cláusula LIKE é formada. Mais especificamente, qual é a localização dos caracteres curinga?
Considere o seguinte:
CREATE TABLE test(
txt_col varchar(10) NOT NULL
)
go
insert test (txt_col)
select CONVERT(varchar(10), row_number() over (order by (select 1))) r
from master..spt_values a, master..spt_values b
go
CREATE INDEX IX_test_data
ON test (txt_col);
go
--Turn on Show Execution Plan
set statistics io on
--A LIKE Clause with a wildcard at the beginning
DBCC DROPCLEANBUFFERS
SELECT txt_Col from test where txt_col like '%10000'
--Results in
--Table 'test'. Scan count 3, logical reads 15404, physical reads 2, read-ahead reads 15416, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
--Index SCAN is 85% of Query Cost
--A LIKE Clause with a wildcard in the middle
DBCC DROPCLEANBUFFERS
SELECT txt_Col from test where txt_col like '1%99'
--Results in
--Table 'test'. Scan count 1, logical reads 3023, physical reads 3, read-ahead reads 3018, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
--Index Seek is 100% of Query Cost for test data, but it may result in a Table Scan depending on table size/structure
--A LIKE Clause with no wildcards
DBCC DROPCLEANBUFFERS
SELECT txt_Col from test where txt_col like '10000'
--Results in
--Table 'test'. Scan count 1, logical reads 3, physical reads 2, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
--Index Seek is 100% of Query Cost
GO
--an "=" clause = does Index Seek same as above
DBCC DROPCLEANBUFFERS
SELECT txt_Col from test where txt_col = '10000'
--Results in
--Table 'test'. Scan count 1, logical reads 3, physical reads 2, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
--Index Seek is 100% of Query Cost
GO
DROP TABLE test
Também pode haver diferença insignificante na criação do plano de consulta ao usar "=" vs "LIKE".
Além dos curingas, a diferença entre =
AND LIKE
dependerá do tipo de servidor SQL e do tipo de coluna.
Veja este exemplo:
CREATE TABLE testtable (
varchar_name VARCHAR(10),
char_name CHAR(10),
val INTEGER
);
INSERT INTO testtable(varchar_name, char_name, val)
VALUES ('A', 'A', 10), ('B', 'B', 20);
SELECT 'VarChar Eq Without Space', val FROM testtable WHERE varchar_name='A'
UNION ALL
SELECT 'VarChar Eq With Space', val FROM testtable WHERE varchar_name='A '
UNION ALL
SELECT 'VarChar Like Without Space', val FROM testtable WHERE varchar_name LIKE 'A'
UNION ALL
SELECT 'VarChar Like Space', val FROM testtable WHERE varchar_name LIKE 'A '
UNION ALL
SELECT 'Char Eq Without Space', val FROM testtable WHERE char_name='A'
UNION ALL
SELECT 'Char Eq With Space', val FROM testtable WHERE char_name='A '
UNION ALL
SELECT 'Char Like Without Space', val FROM testtable WHERE char_name LIKE 'A'
UNION ALL
SELECT 'Char Like With Space', val FROM testtable WHERE char_name LIKE 'A '
Usando o MS SQL Server 2012 , os espaços à direita serão ignorados na comparação, exceto LIKE
quando o tipo de coluna for VARCHAR
.
Usando o MySQL 5.5 , os espaços à direita serão ignorados para =
, mas não para LIKE
, ambos com CHAR
e VARCHAR
.
Usando o PostgreSQL 9.1 , os espaços são significativos com ambos =
e LIKE
usando VARCHAR
, mas não com CHAR
(consulte a documentação ).
O comportamento com LIKE
também difere com CHAR
.
Usar os mesmos dados acima, usar um explícito CAST
no nome da coluna também faz a diferença :
SELECT 'CAST none', val FROM testtable WHERE char_name LIKE 'A'
UNION ALL
SELECT 'CAST both', val FROM testtable WHERE
CAST(char_name AS CHAR) LIKE CAST('A' AS CHAR)
UNION ALL
SELECT 'CAST col', val FROM testtable WHERE CAST(char_name AS CHAR) LIKE 'A'
UNION ALL
SELECT 'CAST value', val FROM testtable WHERE char_name LIKE CAST('A' AS CHAR)
Isso retorna apenas linhas para "CAST both" e "CAST col".
A palavra-chave LIKE, sem dúvida, vem com uma "etiqueta de preço de desempenho" anexada. Dito isto, se você tiver um campo de entrada que possa incluir caracteres curinga para serem usados em sua consulta, recomendo usar LIKE apenas se a entrada contiver um dos curingas. Caso contrário, use o padrão igual à comparação.
Cumprimentos...
No Oracle, um 'like' sem curingas retornará o mesmo resultado que um 'igual', mas poderá exigir processamento adicional. De acordo com Tom Kyte , a Oracle tratará um 'like' sem curingas como 'igual' ao usar literais, mas não ao usar variáveis de ligação.