Expressões Regulares em Banco de Dados, muito além do Like – Parte 02
III – Busca
de Expressões Regulares
no SGBD Oracle
O Oracle versão 10G , ou superior, possui as seguintes
funções de busca
baseada no uso
de expressões regulares:
REGEXP_LIKE(),REGEXP_REPLACE(),REGEXP_SUBSTR() e REGEXP_COUNT(), essa última novidade
da versão 11G.
REGEXP_LIKE(x, padrão[,opção_correspondente])
- Realiza a busca
em
x da
expressão regular
definida no parâmetro padrão. Opção_correspondente
pode ser definida
com os seguintes
valores:
- ‘c’ - Especifica correspondência com diferenciação de maiúsculas e minúsculas( Padrão – case-Sensitive)
- ‘i’ - Especifica a busca sem diferenciação de caracteres maiúsculos e minúsculos(case-Insensitive)
- ‘n’ - Que permite usar o operador de correspondência com qualquer caractere.
- ‘m’ - Que trata x como uma linha múltipla.
- ‘x’ - ignora espaços em branco.
A semelhança com
o comando LIKE não
é mera coincidência,
mas o leitor
já poderá notar
a maior flexibilidade no uso de REGEXP_LIKE
em relação
ao operador LIKE.
Considerando que a melhor
maneira de aprender
é com a utilização prática,
estarei ilustrando a utilização com
vários pequenos
exemplos
de uso, que
poderão ser estudados e adaptados a outras necessidades.
Nesse primeiro exemplo
suponhamos a necessidade de achar em uma tabela de clientes
todos os clientes
com data
de nascimento entre 1970 e 1975. Podemos realizar
a busca, usando expressões
regulares, da seguinte
forma:
SELECT nome, sobrenome, data_nascimento
FROM clientes
WHERE REGEXP_LIKE(TO_CHAR(data_nascimento, 'YYYY'), '^197[0-5]$');
Devemos ter em
mente que
ERs, ao contrário do operador LIKE, tem a tendência
de nos trazer
tudo, sem
a necessidade dos coringas (%), dessa forma precisamos estar atentos para restringir
a informação de retorno
ao desejado.
Para quem não
tem ainda experiência
com expressões
regulares, podemos definir,
como exemplo,
um
conjunto numérico de muitas formas, de forma que [0123456789] é igual
à [0-9], esses detalhes
podem tornar seu
código muito
mais legível
e elegante, e economizar
digitação é claro. No exemplo anterior
poderíamos ler
a expressão da seguinte
forma, retorne todos
os clientes (nome,
sobrenome, data
de nascimento), cujo ano de
nascimento se inicie com 197(“^197”) e
termine (“$” ) com um
elemento de 0 até
5 (“[0-5]$”).
Outro exemplo de recuperação de registros
dos clientes, podemos ter
a necessidade de recuperar
em uma base
qualquer os clientes cujo sobrenome
se iniciem com ‘C’ ou
‘c’, realmente um
exemplo simples.
Nesse caso podemos lançar mão, por exemplo, do seguinte
código, onde
observem o metacaracter “^” garante a busca
no inicio do campo e a opção correspondente
“i” uma busca
case-insensitive:
SELECT nome, sobrenome, data_nascimento
FROM clientes
WHERE REGEXP_LIKE(sobrenome, '^C’,
‘i’);
Para recuperar os registros
dos clientes que
se chamem Flávio ou Flavio, podemos usar o seguinte o código:
SELECT nome, sobrenome, data_nascimento
FROM clientes
WHERE REGEXP_LIKE(nome
, '^FL[aá]’, ‘i’);
Note nesse caso que os elementos
da lista “a ou
“á” não possuem separadores
e que a busca
é case-insentive.
Nesse ponto muitos
podem colocar que
esse mesmo
tipo de busca
pode ser feita por meio de
LIKE em SQL ou
por meio
de buscas textuais.
Nesse instante devemos pensar
que para cada caso
existe uma solução mais
adequada, e que para
nesses exemplos a solução
mais simples
elegante é realmente
lançar mão
das ERs, mas deixo bem
claro que
existirão situações que
a utilização de soluções
textuais, fonéticas,
ou até
mesma a combinação
de várias dessas técnicas combinadas ainda com Ers,
poderão se mostrar úteis ou
até mesmo
necessárias.
Continuando com nossos
exemplos, podemos trazer uma
seleção de linhas
em que
o nome possua exatamente
cinco letras:
SELECT nome
FROM clientes
WHERE REGEXP_LIKE(nome , '^.....$','i');
Podemos observar que
o número de caracteres
desejadas também poderia
ser expresso
da seguinte maneira,
no bloco WHERE da nossa
expressão:
REGEXP_LIKE(nome, '^.{5}$','i');
Nesse momento
vamos supor que
queremos procurar dois nomes ao mesmo tempo, ou ‘joão’
ou ‘maria’:
SELECT nome
FROM clientes
WHERE REGEXP_LIKE(nome , '(joão|maria)','i');
Estes exemplos simples
tiveram como objetivo,
demonstrar tanto
a versatilidade quanto a simplicidade das ERS, e como
sua utilização
pode se expandir para
expnadir para muito
além do nosso
conhecido comando
LIKE.
Não poderíamos deixar de citar
que podemos lançar
mão de ERs nos
SGBDs para outras funções
que não
somente a busca,
podemos utiliza-los, por exemplo para restringir
entradas nos
SGBDs. Para tanto
podemos utilizar também
as ERs para construção de
constraints, por exemplo,
para definir o formato que o números de telefones
devem ser armazenados no SGBD, por
exemplo (xxx) xxx-xxxxx, poderíamos lançar mão do seguinte comando:
ALTER
TABLE cliente
ADD (CONSTRAINT formato_numero_telefoneCHECK (REGEXP_LIKE(numero_telefone,'^\([[:digit:]]{3}\) [[:digit:]]{3}-[[:digit:]]{4}$')));
Além de REGEXP_LIKE o Oracle disponibiliza as seguintes funções com suporte a expressões
regulares:
REGEXP_REPLACE() – O uso dessa função é para procurar um padrão e substituí-lo por um
string dada
REGEXP_SUBSTR() – Retorna parte de uma string com recursos avançados. estende as
funcionalidades da função SUBSTR, deixando você pesquisar uma string para uma expressão
regular padrão. Esta função é útil se você precisar o conteúdo de uma string, mas não
corresponder a sua posição na string original. A função retorna a string como VARCHAR2 ou
CLOB.
REGEXP_COUNT() –Novidade do Oracle 11G - , Usado para obter a quantidade de vezes que
uma expressão regular ocorre em uma string.
As expressões regulares possuem várias vantagens sobre os tradicionais comandos SQLs (LIKE, INSTR, SUBSTR e REPLACE) desses apenas o operador LIKE possui facilidades de busca ( % e _ ), e mesmo assim não suporta mecanismos de busca de padrões ou expressões complexas, sendo muito difícil reproduzir expressões regulares complexas com comandos SQL
IV – E quanto a índices?
Todos sabemos que os índices são um fator muito importante na busca de informações em função da melhor desempenho que podem proporcionar as buscas. Assim como com a utilização em SGBDs do comando LIKE , os índices padrões criados em um determinado campo não são utilizados nas buscas por ERs, no entanto, isso é muito importante, você pode criar índices baseados em função para implementar desempenho em suas consultas com ERs, caso contrário suas consultas com ERs farão uma varredura completa na tabela(full table scan) o que poderá causar contenção no banco de dados.
V – Para saber mais
KLEENE, STEPHEN COLE ,?MATHEMATICAL LOGIC, DOVER SCIENCE 2002 1.Ed
Links
http:/www.aurelio.net
http://download.oracle.com/docs/cd/B19306_01/server.102/b14200/functions129.htm
http://pt.wikipedia.org/wiki/Express%C3%A3o_regular
http://pt.wikipedia.org/wiki/POSIX
http://www.oracle.com/technology/software/products/sql/index.html
First Expressions, Jonathan Gennick, http://www.oracle.com/technology/oramag/oracle/03-sep/o53sql.html