MySQL - REGEXP (EXPRESSÕES REGULARES) no MySQL
Expressões regulares são um tema, diriamos, meio "cabeludo" pois a sua sintaxe não ajuda muito no quesito "dicas de como funciona". Geralmente trabalhar bem com REGEXP significa muito tempo de prática para "pegar o jeito" mais do que decorar livros ou soluções prontas. Mas não é por isto que vamos desanimar de trabalhar com elas, pois são extremamente poderosas.
O que alguns podem não saber, ou sabem mas não estão familiarizados, é que podemos utilizar também nos bancos de dados as famosas REGEXPs, alguns com mais outros com menos restrições. As REGEXPs também nos passam a falsa ilusão de que podemos utilizá-las não só para filtrar dados mas também para pegar "pedaços" da informação já selecionada. Vamos tratar disto mais adiante.
Nosso foco hoje é ver um pouco das expressões regulares aplicadas no MySQL, as armadilhas, equivocos e soluções desta ferramenta tão poderosa.
Infelizmente o MySQL não aceita todas as REGEXPs que, por exemplo, o PHP aceita. Abaixo apresento algumas das que podem ser utilizadas:
- ^ Início de string
- $ Fim de string
- . Qualquer character único
- [...] Qualquer caractere listado entre colchetes
- [^...] Qualquer caractere não listado entre colchetes
- p1|p2|p3 Revezamento; combina qualquer dos padrões p1, p2, or p3
- * Zero ou mais instâncias do elemento precedente
- + One ou mais instâncias do elemento precedente
- {n} n instâncias do elemento precedente
- {m,n} m até n instâncias do elemento precedente
http://dev.mysql.com/doc/refman/5.1/en/regexp.html
Vamos começar assumindo nossa tabela padrão (tabela 'site').
id | nome | url | tipo |
---|---|---|---|
1 | Wikipedia Home | http://www.wikipedia.org/ | home |
2 | Wikipedia NASA | http://en.wikipedia.org/wiki/NASA | article |
3 | Wikipedia Planetas | http://pt.wikipedia.org/wiki/Planeta | article |
Existem três abordagens que podemos seguir que descrevo abaixo:
USANDO WHERE e REGEXP
Uma é a seleção de resultados baseado em um REGEXP feito da cláusula WHERE.
Alguns regexps podem não funcionar da mesma maneira que no javascript ou PHP. Vale fazer testes e também, sempre que possível, utilizar várias referências (não tão genéricas) para que o MySQL consiga encontrar o que você quer.
SELECT * FROM `site` WHERE url REGEXP 'http\:\/\/[a-z]{2}\.wikipedia'
id | nome | url | tipo |
---|---|---|---|
2 | Wikipedia NASA | http://en.wikipedia.org/wiki/NASA | article |
3 | Wikipedia Planetas | http://pt.wikipedia.org/wiki/Planet | article |
A query abaixo traz o mesmo resultado só que de maneira mais genérica.
SELECT * FROM `site` WHERE url REGEXP 'http\:\/\/[a-z]{2}\\.'
O que estamos dizendo para o MySQL é que ele traga tudo que possui 'http://', depois disto tudo que tenha duas letras minúsculas e, finalmente, um ponto depois destas duas letras. A diferença entre as duas queries está no fato de, na primeira, especificarmos que queremos após o ponto '.' a palavras 'wikipedia', o que no caso dos dados da tabela não faz diferença.
Bem, esta é a idéia básica ao utilizar REGEXP no WHERE. Faça testes e variações disto.
USANDO REGEXP no SELECT
Podemos utilizar o REGEXP dentro do resultado de um SELECT também, porém, neste caso, não será possível retornar pedaços do resutado selecionados com base na extressão regular. Aliás este é um erro bem comum de muitas pessoas, imaginar que o REGEXP consegue fazer a mesma função no MySQL que um preg_match() no PHP. Infelizmente isto não é possível. O que conseguimos como retorno é tão somente um boolean 1 ou 0 indicando se o padrão foi encontrado ou não.
SELECT *,url REGEXP 'http\:\/\/[a-z]{2}\\.' AS existe FROM site
id | nome | url | tipo | existe |
1 | Wikipedia Home | http://www.wikipedia.org/ | home | 0 |
2 | Wikipedia NASA | http://en.wikipedia.org/wiki/NASA | article | 1 |
3 | Wikipedia Planetas | http://pt.wikipedia.org/wiki/Planeta | article | 1 |
O REGEXP acima é o mesmo que do exemplo anterior, só que ao invés de ser declarado no WHERE ele é declarado no SELECT.
Para conseguir este tipo de retornom, ou seja, pegar um pedaço da string retornada pelo SELECT, devemos utilizar as funções de string como SUBSTRING_INDEX(), RIGHT() e etc. Este assunto merece um artigo à parte mas você pode consultar o link abaixo para ter uma idéia do que fazer.
http://dev.mysql.com/doc/refman/5.0/en/string-functions.html
NOT REGEXP
NOT REGEXP atua como um inversor, ou negação, do REGEXP, ou seja, se REGEXP retorna 'A' NOT REGEXP, com a mesma sintaxe, retorna qualquer outra coisa menos 'A'.
SELECT * FROM `site` WHERE url NOT REGEXP 'http\:\/\/[a-z]{2}\.wikipedia'
id | nome | url | tipo |
---|---|---|---|
1 | Wikipedia Home | http://www.wikipedia.org/ | home |
O comando acima retorna a seleção inversa de "REGEXP 'http\:\/\/[a-z]{2}\.wikipedia'" do primeiro exemplo graças ao NOT REGEXP.
Bem, é isso ai.
Abraços
Comentários
Postar um comentário