SQL e Regex – Entenda quando e como usar em instruções SQL

SQL e Regex – Entenda quando e como usar em instruções SQL

23 de janeiro de 2019 1 Por Ramos de Souza Janones
Powered by Rock Convert

Aprenda o conceito e uso de Regex em SQL, o MySQL e para as mais diversas linguagens de programação que possuem suas próprias engines de regex embutidas.

Neste artigo você aprenderá um pouco do conceito e uso de Regex em SQL, não apenas para o MySQL para para as mais diversas linguagens de programação que possuem suas próprias engines de regex embutidas. 

Imagine o seguinte cenário:

Você precisa selecionar registros que tenham no meio do texto números de telefone para excluir (moderação automática).

Exemplo de formatos: 9933459879 93345987(21)932324343(21)9 3232 4343, etc…

Como você resolveria este problema?

Resposta curta: O uso de uma query parecida com esta:

 

select * from tabela where comentario REGEXP '.*[0-9]{2}9[0-9]{8}.*|.*[0-9]{2} 9 [0-9]{4} [0-9]{4}.*';

Vamos entender mais sobre REGEX no SQL

Para explicar vamos pegar o mesmo exemplo no inicio do artigo, explorando números de telefones e CPF:

Se são os próprios usuários que colocam os telefones nos comentários, então não há muito controle sobre o formato.

Claro que você pode considerar alguns formatos mais comuns. Pelos exemplos, podem ser os 9 dígitos do número do celular, todos juntos ou separados por espaços (9999999999 9999 9999 ou 99999 9999), sendo o DDD opcional.

Na resposta curtra no inicio deste artigo sugerimos uma regex bem complexa para contemplar estes (e muitos outros) casos, mas a sintaxe de regex suportada pelo MySQL infelizmente é um pouco limitada e não vai suportar todos os recursos propostos, como \d para representar dígitos ou os lookaheads e lookbehinds (os trechos que começam com (?=(?! e (?<!).

Sendo assim, segue uma alternativa que verifica alguns formatos:

select * from tabela where comentario REGEXP '(^|[^0-9])(\(?0?[0-9]{2}\)?)?9 ?[0-9]{4} ?[0-9]{4}([^0-9]|$)';

(^|[^0-9]):| significa “ou”. Portanto, este trecho significa “início da string” (^ou “qualquer coisa que não seja número” (o [^ significa que não quero o que vem depois, ou seja, não quero 0-9 – nenhum dígito de zero a 9).

Isso garante que até aqui eu posso estar no início da string (vai que o telefone já está no início), ou tem qualquer caractere que não seja um número (evitando que pegue casos como 3393333333333333333).

Em seguida temos (\\(?0?[0-9]{2}\\)?)?. Vamos por partes, de dentro para fora:

  • 0?[0-9]{2} – um zero opcional (0? – o ? indica “zero ou uma ocorrência“, o que é o mesmo que dizer “opcional”), seguido de 2 dígitos ([0-9] é qualquer dígito de 0 a 9, e {2} que dizer “duas ocorrências“), pois o DDD pode ser escrito como 11 ou 011
  • \\(? e \\)? – os parênteses podem ser opcionais. Fiz assim porque somente os parênteses () têm significado especial em regex, pois servem para agrupar sub-expressões. Por isso temos que escapá-los com \\.
  • por fim, todo este trecho está entre parênteses (ou seja, agrupado em uma única sub-expressão), e o ? no final faz todo este trecho ser opcional.

Ou seja, o DDD é opcional.

Depois temos 9 ?, que é o número 9 seguido de um espaço opcional (repare que há um espaço antes do ?, ou seja, o espaço que é opcional, não o 9). Aqui estou assumindo que serão somente números de celular que começam com 9 – lembrando que futuramente poderemos ter celulares que começam com 8, 7, etc, então fica a seu critério deixar sempre 9 ou trocar para [0-9] (ou [7-9] se quiser que comece somente com 7, 8 ou 9, etc).

Curso completo de Games, inclusive Realidade Aumentada.Powered by Rock Convert

Depois temos [0-9]{4} (4 dígitos), seguido de um espaço opcional, mais 4 dígitos.

LEIA TAMBÉM: 22 Livros de Marketing Digital para ler em 2019

E por fim, temos ([^0-9]|$): qualquer caractere que não seja número ou o final da string ($). Isso também garante que não vai pegar mais dígitos que o necessário, evitando que pegue por exemplo 3393333333333333333.

Neste SQLfiddle você pode ver esta query funcionando.


Se quiser incrementar, pode colocar o separador como hífen ou espaço, por exemplo, assim seriam aceitos números como 9 9123-4567 ou 99123-4567. Basta trocar os espaços opcionais por [ \\-]?(um espaço ou um hífen, opcional). A regex ficaria assim:

select * from tabela where comentario REGEXP
'(^|[^0-9])(\(?0?[0-9]{2}\)?)?9[ \-]?[0-9]{4}[ \-]?[0-9]{4}([^0-9]|$)';

Veja aqui ela funcionando.

Também é possível adicionar um espaço opcional depois do DDD:

(^|[^0-9])(\(??[0-9]{2}\)?)? ?9 ?[0-9]{4} ?[0-9]{4}([^0-9]|$)
                               

Sem esse espaço, o DDD é ignorado para casos como (11) 9 9123 4567 – somente o número de telefone é capturado pela regex, mas o DDD não, veja aqui um exemplo. Já colocando o espaço opcional, o DDD também é capturado, veja aqui a diferença.

Outro detalhe é que estamos considerando apenas números de celular. Mas ainda existem números de telefone com 8 dígitos (em residências nem tanto, mas em empresas, ainda é bem comum). Se também quiser considerar estes números, basta colocar o 9 como opcional:

(^|[^0-9])(\(??[0-9]{2}\)?)? ?9? ?[0-9]{4} ?[0-9]{4}([^0-9]|$)
                                 ^^

Só lembrando que, como são os usuários que digitam seus números, sempre poderá haver algum formato estranho que você não previu. E quanto mais possibilidades, mais complexa vai ficando a regex.

Por exemplo, a regex que sugeri só considera um espaço em branco opcional. Mas se quiser que tenha mais de um espaço, pode trocar o ? por * (zero ou mais ocorrências), ou limitar a quantidade com chaves (por exemplo, {0,3} limita entre 0 a 3 ocorrências).

Há também a possibilidade de um CPF ser confundido com um telefone, já que ambos podem ser escritos sem nenhum separador (43912341222 pode ser tanto um CPF quanto um DDD + telefone – mesmo que as pessoas costumem escrever o CPF como 439.123.412-22, quem garante que não vai ter um caso assim? De qualquer forma, veja se isso se aplica aos seus casos). Enfim, regex não é um negócio tão “mágico” assim, e cabe a você avaliar se vai confiar tanto nela ao ponto de remover automaticamente qualquer coisa que ela pegar…

Conclusão

A maioria das linguagens de programação possui engines de regex mais modernas, o que permite escrever expressões como essa, por exemplo (que usa \b para delimitar os telefones, sem precisar usar o “truque” que fiz acima com (^|[^0-9]) e ([^0-9]|$), além de usar \d como um atalho para [0-9] e \s para espaços).

Outros tutoriais e dicas sobre PHP:

Banco de dados

Artigos e dicas sobre banco de dados que você vai gostar:

MongoDB

– Principais diferenças entre MongoDB e MySQL ou outro RDBMS

– Southbank Software apresenta dbKoda: uma ferramenta de desenvolvimento Open Source para MongoDB

MySQL e Instruções SQL em geral

– SQL e Regex – Entenda quando e como usar em instruções SQL

– MySQL – Manter o formato Date e DateTime em formato dd/mm/Year e dd/mm/Year:HH:mm:ss

– SQL – O que são VIEWS SQL, vantagens e desvantagens

– Instrução Insert MySQL e JSON com todos os bancos brasileiros

– PHP e MySQL – Entendendo as codificações iso-8859-1 e UTF-8 e outras

– Como redefinir a senha de root do MySQL ou do MariaDB

– Para que serve uma MySQL Transaction?

– Banco de Dados – Índices desnecessários no banco são um problema?

– Entenda a diferença entre LIKE, IN e BETWEEN no MySQL

– LinkedIn desenvolve a ferramenta MySQL Query Analyzer

– Como otimizar consultas MySQL

– Quando é interessante desnormalizar o banco de dados?

– Entenda Views em SQL, vantagens e desvantagens

– O que é normalização de banco de dados

– Por que não devemos usar funções do tipo mysql_*

SQL – Entenda as diferenças entre aspas simples e duplas

– SQL – Not IN ou Not EXISTS quando usar?

– SQL – Entendendo JOINS

– PHP Do Zero Ao Profissional – Análise do Curso

Leia mais sobre Banco de Dados

 

LEIA TAMBÉM:  Ferramenta MySQL Query Analyzer
Siga os bons!

Ramos de Souza Janones

Janones, é um empreendedor brasileiro apaixonado por empreendedorismo e tecnologia. Ao longo dos anos trabalhando com o desenvolvimento de softwares desktop desde a linguagem Clipper, passando pelo Delphi e atualmente com Java.

Optou pela formação de Publicidade e Marketing por sua segunda empresa de tecnologia ter participado do "boom" da internet nos anos 90 e na procura de melhorar seus conhecimentos em negócios.

Em razão da principal formação e profundos conhecimentos em programação e banco de dados, é capaz de realizar o desenvolvimento de aplicativos web, desktop e mobile com maior criatividade e inovação que profissionais de desenvolvimento com uma formação única e mais especifica, dedicada somente ao desenvolvimento de softwares.

Com toda sua experiência com empresas de software, sua formação e paixão por negócios escreveu o livro "Marketing para Empresas e Profissionais de Software", publicado pela editora carioca Ciência Moderna em 2012. Além de outros livros sobre programação.

Últimos posts por Ramos de Souza Janones (exibir todos)

Sumário
SQL e Regex - Entenda quando e como usar em instruções SQL
Nome do artigo
SQL e Regex - Entenda quando e como usar em instruções SQL
Descrição
Aprenda o conceito e uso de Regex em SQL, o MySQL e para as mais diversas linguagens de programação que possuem suas próprias engines de regex embutidas. 
Autor
Nome
Ramos da Informática
Logo



Frontend Do Zero Ao Profissional