Existem três abordagens separadas para comparação com padrão
fornecidas pelo PostgreSQL: o operador
LIKE
do SQL,
o operador mais recente
SIMILAR TO
do SQL99, e as
expressões regulares no estilo POSIX.
Além destas, a função de comparação com padrão
SUBSTRING
também está disponível, utilizando
tanto o estilo SQL99 quanto as expressões regulares POSIX.
Dica: Havendo necessidade de comparação com padrão não atendidas, deve ser considerado o desenvolvimento de uma função definida pelo usuário em Perl ou Tcl.
LIKE
cadeia_de_caracteres LIKE filtro [ESCAPE caractere_de_escape] cadeia_de_caracteres NOT LIKE filtro [ESCAPE caractere_de_escape]
Cada filtro define um conjunto de cadeias de caracteres.
A expressão LIKE
retorna verdade se a
cadeia_de_caracteres estiver contida no conjunto de
cadeias de caracteres representado pelo filtro (Como
esperado, a expressão NOT LIKE
retorna
falso quando LIKE
retorna verdade, e vice-versa.
A expressão equivalente seria
NOT (cadeia_de_caracteres LIKE
filtro)).
Quando o filtro não possui os caracteres percentagem
ou sublinhado, o filtro representa apenas
a própria cadeia de caracteres; neste caso LIKE
atua
como o operador igual. O sublinhado (_) no
filtro significa (corresponde a) qualquer
caractere único; o caractere percentagem (%) corresponde a
qualquer cadeia com zero ou mais caracteres.
Alguns exemplos:
'abc' LIKE 'abc' true 'abc' LIKE 'a%' true 'abc' LIKE '_b_' true 'abc' LIKE 'c' false
A comparação com padrão LIKE
sempre abrange toda a cadeia
de caracteres. Para haver correspondência com o padrão em qualquer posição da
cadeia de caracteres, o filtro precisa começar e terminar pelo caractere percentagem.
Para corresponder ao próprio caractere sublinhado ou percentagem, e não a outros caracteres, estes caracteres no filtro devem estar precedidos pelo caractere de escape. O padrão para caractere de escape é a contrabarra, mas um outro caractere pode ser definido através da cláusula ESCAPE. Para corresponder ao próprio caractere de escape, devem ser escritos dois caracteres de escape.
Deve ser observado que a contrabarra possui significado especial nas
cadeias de caracteres e, portanto, para escrever um filtro contendo uma
contrabarra devem ser escritas duas contrabarras na consulta. Assim sendo, escrever
um filtro correspondente à contrabarra significa escrever quatro contrabarras
na consulta, o que pode ser evitado escolhendo um caractere de escape diferente
na cláusula ESCAPE; assim a contrabarra deixa de
ser um caractere especial para o LIKE
(Mas continua sendo especial
para o analisador de cadeias de caracteres e, por isso, continuam sendo necessárias
duas contrabarras).
Também é possível fazer nenhum caractere servir de escape declarando ESCAPE ''. Esta declaração tem como efeito desativar o mecanismo de escape, tornando impossível evitar o significado especial dos caracteres sublinhado e percentagem presentes no filtro.
A palavra chave ILIKE pode ser utilizada no lugar do LIKE para fazer a comparação não diferenciar letras maiúsculas de minúsculas, conforme a localização ativa. Isto não faz parte do padrão SQL, sendo extensão do PostgreSQL.
O operador ~~ equivale ao
LIKE
, enquanto ~~* equivale ao
ILIKE
. Também existem os operadores
!~~ e !~~*, representando
o NOT LIKE
e o NOT ILIKE
.
Todos estes operadores são específicos do
PostgreSQL.
SIMILAR TO
e as expressões regulares do
SQL99cadeia_de_caracteres SIMILAR TO filtro [ESCAPE caractere_de_escape] cadeia_de_caracteres NOT SIMILAR TO filtro [ESCAPE caractere_de_escape]
O operador SIMILAR TO
retorna verdade ou falso
conforme o filtro corresponda ou não à cadeia de caracteres fornecida.
Este operador é muito semelhante ao LIKE
, exceto
por interpretar o filtro utilizando a definição de expressão regular do
SQL99.
As expressões regulares do SQL99 são um cruzamento curioso
entre a notação do LIKE
e a notação das expressões
regulares comuns.
Da mesma forma que o LIKE
, o operador
SIMILAR TO
somente tem êxito quando o filtro corresponde
a toda cadeia de caracteres; é diferente da prática comum para expressões
regulares, onde o filtro pode corresponder a qualquer parte da cadeia de caracteres.
Também como o
LIKE
, o operador SIMILAR TO
utiliza
% e _ como caracteres curingas, representando qualquer
cadeia de caracteres e qualquer caractere único, respectivamente (sendo
semelhantes aos .* e . das expressões regulares
POSIX).
Além destas facilidades tomadas emprestada do LIKE
, o
SIMILAR TO
suporta os seguintes metacaracteres
para comparação com padrão tomados emprestado das expressões regulares POSIX:
| representa a alternância (uma das duas alternativas).
* representa a repetição do item anterior zero ou mais vezes.
+ representa a repetição do item anterior uma ou mais vezes.
Os parênteses () podem ser utilizados para agrupar itens num único item lógico.
A expressão de colchetes [...] especifica uma classe de caracteres, do mesmo modo que na expressão regular POSIX.
Observe que a repetição limitada (bounded repetition) (? e {...}) não está disponível, embora exista no POSIX. Além disso, o ponto (.) não é um metacaractere.
Da mesma forma que no LIKE
, a contrabarra cancela o significado
especial de qualquer um destes metacaracteres; ou um caractere de escape diferente
pode ser especificado por meio do ESCAPE.
Alguns exemplos:
'abc' SIMILAR TO 'abc' true 'abc' SIMILAR TO 'a' false 'abc' SIMILAR TO '%(b|d)%' true 'abc' SIMILAR TO '(b|c)%' false
A função SUBSTRING
com três parâmetros,
SUBSTRING(cadeia_de_caracteres FROM
filtro FOR
escape)
, permite a extração da
parte da cadeia de caracteres correspondente à expressão regular SQL99
no filtro. Assim como em SIMILAR TO, o filtro especificado
deve corresponder a toda a cadeia de caracteres do dado, senão a função
falha e retorna nulo. Para indicar a parte do filtro que deve ser
retornada em caso de sucesso, o SQL99 especifica que o filtro deve conter
duas ocorrências do caractere de escape seguido por
aspas ("). O texto correspondente à parte do
filtro entre estes marcadores é retornada.
Alguns exemplos:
SUBSTRING('foobar' FROM '%#"o_b#"%' FOR '#') oob SUBSTRING('foobar' FROM '#"o_b#"%' FOR '#') NULL
A Tabela 6-11 lista os operadores disponíveis para comparação com padrão utilizando as expressões regulares POSIX.
Tabela 6-11. Operadores de comparação para expressões regulares
Operador | Descrição | Exemplo |
---|---|---|
~ | Corresponde à expressão regular, diferenciando maiúsculas/minúsculas | 'thomas' ~ '.*thomas.*' |
~* | Corresponde à expressão regular, não diferenciando maiúsculas/minúsculas | 'thomas' ~* '.*Thomas.*' |
!~ | Não corresponde à expressão regular, diferenciando maiúsculas/minúsculas | 'thomas' !~ '.*Thomas.*' |
!~* | Não corresponde à expressão regular, não diferenciando maiúsculas/minúsculas | 'thomas' !~* '.*vadim.*' |
As expressões regulares POSIX fornecem uma forma
mais poderosa para comparação com padrão
que os operadores LIKE
e
SIMILAR TO
.
Muitas ferramentas do Unix, como egrep,
sed e awk, utilizam uma linguagem para
comparação com padrão semelhante à descrita aqui.
Uma expressão regular é uma seqüência de caracteres que é uma
definição abreviada de um conjunto de cadeias de caracteres (um conjunto
regular). Uma cadeia de caracteres é dita correspondendo a uma expressão
regular se for membro do conjunto regular descrito pela expressão regular.
Assim como no LIKE
, os caracteres do filtro correspondem
exatamente aos caracteres da cadeia de caracteres, a não ser que sejam caracteres
especiais da linguagem da expressão regular --- porém as expressões regulares utilizam
caracteres especiais diferentes dos utilizados pelo LIKE
.
Ao contrário do LIKE
, uma expressão regular
pode corresponder a qualquer parte da cadeia de caracteres, a não ser que a expressão
regular esteja explicitamente ancorada ao início ou ao fim da
cadeia de caracteres.
Alguns exemplos:
'abc' ~ 'abc' true 'abc' ~ '^a' true 'abc' ~ '(b|d)' true 'abc' ~ '^(b|c)' false
A função SUBSTRING
com dois parâmetros,
SUBSTRING(cadeia_de_caracteres FROM
filtro)
, permite extrair a parte da
cadeia de caracteres correspondente à expressão regular SQL99 no filtro. A função
retorna nulo quando não há correspondência, senão retorna a parte do texto que
corresponde ao filtro. Mas se o filtro contiver parênteses, a parte do texto
correspondente à primeira subexpressão entre parênteses (aquela
cujo abre parênteses vem primeiro) é
retornada. Pode ser colocado parênteses envolvendo toda a expressão
se for desejado utilizar parênteses em seu interior sem disparar esta
exceção.
Alguns exemplos:
SUBSTRING('foobar' FROM 'o.b') oob SUBSTRING('foobar' FROM 'o(.)b') o
As expressões regulares (REs), conforme definidas no POSIX 1003.2, estão presentes em duas formas: REs modernas (as do egrep aproximadamente; chamadas no 1003.2 de REs "estendidas"), e REs obsoletas (as do ed aproximadamente; REs "básicas" do 1003.2). O PostgreSQL implementa a forma moderna.
Uma expressão regular (moderna) é composta por uma ou mais subdivisões não vazias, separadas por |. A expressão corresponde a qualquer coisa que corresponda a uma das suas subdivisões.
Uma subdivisão é uma ou mais peças, concatenadas. Equivale a uma correspondência para a primeira, seguida por uma correspondência para a segunda, etc.
Uma peça é um átomo, possivelmente seguido por um único *, +, ? ou limite. Um átomo seguido por um * corresponde a uma série de 0 ou mais ocorrências do átomo. Um átomo seguido por um + corresponde a uma série de 1 ou mais ocorrências do átomo. Um átomo seguido por um ? corresponde a uma série de 0 ou 1 ocorrências do átomo.
Um limite é uma { seguida por um número decimal inteiro sem sinal, possivelmente seguido por uma , possivelmente seguida por um número decimal inteiro sem sinal, sempre seguido por uma }. Os inteiros devem estar entre 0 e RE_DUP_MAX (255) inclusive e, havendo dois deles, o primeiro não pode ser maior que o segundo. Um átomo seguido por um limite contendo um inteiro i e nenhuma vírgula, corresponde a uma série de exatamente i ocorrências do átomo. Um átomo seguido por um limite contendo um inteiro i e uma vírgula, corresponde a uma seqüência de i ou mais ocorrências do átomo. Um átomo seguido por um limite contendo dois inteiros i e j, corresponde a uma série de i até j (inclusive) ocorrências do átomo.
Nota: Um operador de repetição (?, *, + ou limites) não pode vir depois de outro operador de repetição. O operador de repetição não pode iniciar uma expressão, uma subexpressão, ou vir depois de ^ ou |.
Um átomo pode ser uma expressão regular entre () (representando a expressão regular), um conjunto vazio de () (representando a cadeia de caracteres nula), uma expressão de colchete (veja abaixo), . (representando qualquer caractere único), ^ (representando a cadeia de caracteres nula no início da cadeia de caracteres da entrada), $ (representando a cadeia de caracteres nula no final da cadeia de caracteres da entrada), uma \ seguida por um dos caracteres ^.[$()|*+?{\ (representando este caractere como sendo um caractere ordinário), uma \ seguida por qualquer outro caractere (representando este caractere como sendo um caractere ordinário, como se a \ não estivesse presente), ou um caractere único sem qualquer outro significado (representando o próprio caractere). Uma { seguida por um outro caractere que não seja um dígito é um caractere ordinário, e não o início de um limite. É ilegal terminar uma expressão regular por uma \.
Observe que a contrabarra (\) possui um significado especial nas cadeias de caracteres e, portanto, para escrever uma constante filtro contendo uma contrabarra devem ser escritas duas contrabarras na consulta.
Uma expressão entre colchetes é uma seqüência de caracteres entre []. Normalmente significa qualquer um dos caracteres da seqüência (mas veja abaixo). Se o conjunto começar por ^, significa qualquer caractere não presente no restante do conjunto (mas veja abaixo). Se dois caracteres do conjunto estiverem separados por -, isto representa a forma abreviada de todos os caracteres do intervalo delimitado por estes dois caracteres (inclusive) na seqüência de arrumação (collating sequence). Por exemplo, [0-9] em ASCII significa qualquer dígito decimal. É ilegal dois intervalos compartilharem uma mesma extremidade como, por exemplo, a-c-e. Os intervalos são dependentes da seqüência de arrumação dos caracteres, e os programas portáveis devem evitar esta dependência.
Para incluir o literal ] na seqüência, deve ser feito com que seja o primeiro caractere (possivelmente após o ^). Para incluir o literal -, deve ser feito com que seja o primeiro ou o último caractere, ou a segunda extremidade de um intervalo. Para utilizar o literal - como a primeira extremidade de um intervalo, deve-se colocá-lo entre [. e .] para torná-lo um elemento de arrumação (veja abaixo). Com estas excessões e algumas outras combinações utilizando [ (veja os próximos parágrafos), todos os outros caracteres especiais, incluindo a \, perdem seu significado especial dentro de uma expressão entre colchetes.
Dentro da expressão entre colchetes, o elemento de arrumação (um caractere, uma seqüência de múltiplos caracteres arrumada como se fosse um único caractere, ou o nome de uma seqüência de arrumação) entre [. e .] representa a seqüência de caracteres deste elemento de arrumação. A seqüência é um único elemento do conjunto da expressão entre colchetes. Uma expressão entre colchetes contendo um elemento de arrumação de múltiplos caracteres pode, portanto, corresponder a mais de um caractere. Por exemplo, se a seqüência de arrumação incluir um elemento de arrumação ch, então a expressão regular [[.ch.]]*c corresponde aos cinco primeiros caracteres de chchcc.
Dentro de uma expressão entre colchetes, um elemento de arrumação entre [= e =] é uma classe de equivalência, representando as seqüências de caracteres de todos os elementos de arrumação equivalentes a este elemento, incluindo o próprio (Se não existirem outros elementos de arrumação equivalentes, o tratamento é como se os delimitadores envoltórios fossem [. e .]). Por exemplo, se o e ^ são membros de uma classe de equivalência, então [[=o=]], [[=^=]] e [o^] são todos sinônimos. Uma classe de equivalência não pode ser a extremidade de um intervalo.
Dentro de uma expressão entre colchetes, o nome de uma classe de caracteres entre [: e :] representa o conjunto de todos os caracteres pertencentes a esta classe. Os nomes das classes de caracteres padrão são: alnum, alpha, blank, cntrl, digit, graph, lower, print, punct, space, upper, xdigit. Estes nomes representam as classes de caracteres definidas em ctype. Uma localização pode fornecer outras. Uma classe de caracteres não pode ser usada como uma extremidade de um intervalo.
Existem dois casos especiais para expressões entre colchetes: as expressões entre colchetes [[:<:]] e [[:>:]] correspondem à cadeia de caracteres nula no início e no fim de uma palavra, respectivamente. Uma palavra é definida como a seqüência de caracteres de palavra que não é nem precedida nem seguida por caracteres de palavra. Um caractere de palavra é um alnum caractere (conforme definido em ctype) ou um sublinhado. Isto é uma extensão, compatível mas não especificada pelo POSIX 1003.2, devendo ser utilizada com cautela em programas onde se deseja a portabilidade para outros sistemas.
Quando a expressão regular puder corresponder a mais de uma parte da cadeia de caracteres, a expressão regular corresponderá à parte que começar primeiro na cadeia de caracteres. Se a expressão regular puder corresponder a mais de uma parte começando no mesmo ponto, corresponderá à mais longa. As subexpressões também correspondem às partes mais longas possíveis, sujeitas à restrição que toda a correspondência seja a mais longa possível, com as subexpressões começando antes na expressão regular tendo prioridade em relação às começando depois. Observe que, deste modo, as subexpressões de maior nível têm prioridade em relação às suas subexpressões componentes de nível mais baixo.
Os comprimentos das correspondências são medidos em caracteres, e não em elementos de arrumação. Uma cadeia de caracteres nula é considerada como sendo mais longa que nenhuma correspondência. Por exemplo, bb* corresponde aos três caracteres do meio de abbbc; (wee|week)(knights|nights) corresponde a todos os dez caracteres de weeknights; quando (.*).* é comparado com abc a subexpressão entre parênteses corresponde a todos os três caracteres; e quando (a*)* é comparado com bc tanto a expressão regular completa quanto a subexpressão entre parênteses correspondem a cadeia de caracteres nula.
Se for especificada uma correspondência que não diferencie letras maiúsculas e minúsculas, o efeito é como se a distinção entre maiúsculas e minúsculas tivesse desaparecido do alfabeto. Quando um caractere alfabético que existe em maiúscula e minúscula aparece como caractere ordinário fora da expressão entre colchetes, este caractere é transformado em uma expressão entre colchetes contendo as duas representações, por exemplo, x se torna [xX]. Quando o caractere aparece dentro da expressão entre colchetes, a representação que falta é adicionada à expressão entre colchetes, portanto (por exemplo) [x] se torna [xX] e [^x] se torna [^xX].
Não existe nenhum limite determinado para o comprimento da expressão regular, a não ser o fato da memória ser limitada. A utilização de memória é aproximadamente linear em relação ao tamanho da expressão regular, e altamente independente da complexidade da expressão regular, exceto para repetições limitadas. As repetições limitadas são implementadas por meio de expansão de macro, gastando muito tempo e espaço quando os contadores são grandes ou as repetições limitadas são aninhadas. Uma expressão regular como, digamos, ((((a{1,100}){1,100}){1,100}){1,100}){1,100} irá (ao fim) fazer quase todas as máquinas existentes esgotarem suas áreas de permuta (swap). [1]
[1] | Tenha em mente que isto foi escrito em 1994. Os números provavelmente são outros, mas o problema continua. |