9.25. Comparações de linha e de matriz #

9.25.1. IN
9.25.2. NOT IN
9.25.3. ANY / SOME (matriz)
9.25.4. ALL (matriz)
9.25.5. Comparação de construtor de linha
9.25.6. Comparação de tipo de dados composto

Esta seção descreve várias construções especializadas para fazer comparações múltiplas entre grupos de valores. Estas formas estão sintaticamente relacionadas às formas de subconsultas da seção anterior, mas não envolvem subconsultas. As formas que envolvem subexpressões de matrizes são extensões do PostgreSQL; as demais estão em conformidade com o padrão SQL. Todas as formas de expressão documentadas nesta seção retornam resultados booleanos (verdade/falso).

9.25.1. IN #

expressão IN (valor [, ...])

O lado direito é uma lista de expressões entre parênteses. O resultado será verdade se o resultado da expressão do lado esquerdo for igual a qualquer uma das expressões do lado direito. Esta é uma notação abreviada de

expressão = valor1
OR
expressão = valor2
OR
...

Note que se a expressão à esquerda resultar em nulo, ou se não houver valores iguais à direita, e pelo menos uma expressão à direita resultar em nulo, o resultado da construção IN será nulo, e não falso. Isso está em conformidade com as regras normais do padrão SQL para combinações booleanas de valores nulos.

9.25.2. NOT IN #

expressão NOT IN (valor [, ...])

O lado direito é uma lista de expressões entre parênteses. O resultado será verdade se o resultado da expressão do lado esquerdo for diferente de todas as expressões do lado direito. Esta é uma notação abreviada de

expressão <> valor1
AND
expressão <> valor2
AND
...

Note que, se a expressão à esquerda resultar em nulo, ou se não houver valores iguais à direita, e pelo menos uma expressão à direita resultar em nulo, o resultado da construção NOT IN será nulo, e não verdade, como se poderia ingenuamente esperar. Isso está em conformidade com as regras normais do padrão SQL para combinações booleanas de valores nulos.

Dica

x NOT IN y equivale a NOT (x IN y) em todos os casos. Entretanto, os valores nulos são muito mais propensos a enganar o novato ao trabalhar com NOT IN do que ao trabalhar com IN. É melhor expressar a condição da forma positiva, se for possível.

9.25.3. ANY / SOME (matriz) #

expressão operador ANY (expressão_de_matriz)
expressão operador SOME (expressão_de_matriz)

O lado direito é uma expressão entre parênteses, que deve gerar um valor de matriz. A expressão à esquerda é avaliada e comparada com cada elemento da matriz usando o operador fornecido, que deve gerar um resultado booleano. O resultado de ANY será verdade se for obtido algum resultado verdade. O resultado será falso se não for encontrado nenhum resultado verdade (incluindo o caso onde a matriz tem zero elementos).

Se a expressão de matriz gerar uma matriz nula, o resultado de ANY será nulo. Se a expressão do lado esquerdo resultar em nulo, o resultado de ANY normalmente é nulo (embora um operador de comparação não estrito possa produzir um resultado diferente). Além disso, se a matriz da direita contiver quaisquer elementos nulos e não for obtido nenhum resultado de comparação resultando em verdade, o resultado de ANY será nulo, e não e falso (novamente, assumindo um operador de comparação estrito). Isso está em conformidade com as regras normais do padrão SQL para combinações booleanas de valores nulos.

SOME é um sinônimo de ANY.

9.25.4. ALL (matriz) #

expressão operador ALL (expressão_de_matriz)

O lado direito é uma expressão entre parênteses, que deve gerar um valor de matriz. A expressão à esquerda é avaliada e comparada com cada elemento da matriz usando o operador fornecido, que deve gerar um resultado booleano. O resultado de ALL será verdade se todas as comparações resultarem em verdade (incluindo o caso onde a matriz tem zero elementos). O resultado será falso se for encontrado algum resultado falso.

Se a expressão de matriz gerar uma matriz nula, o resultado de ALL será nulo. Se a expressão à esquerda produzir nulo, o resultado de ALL normalmente é nulo (embora um operador de comparação não estrito possa produzir um resultado diferente). Além disso, se a matriz à direita contiver quaisquer elementos nulos, e não for obtido nenhum resultado de comparação falso, o resultado de ALL será nulo, e não verdade (novamente, assumindo um operador de comparação estrito). Isso está em conformidade com as regras normais do padrão SQL para combinações booleanas de valores nulos.

9.25.5. Comparação de construtor de linha #

construtor_de_linha operador construtor_de_linha

Cada lado da expressão é um construtor de linha, conforme descrito na Seção 4.2.13. Os dois construtores de linha devem ter o mesmo número de campos. O operador fornecido é aplicado a cada par de campos correspondentes. (Como os campos podem ter tipos de dados diferentes, isto significa que pode ser selecionado um operador específico diferente para cada par.) Todos os operadores selecionados devem ser membros de alguma classe de operadores de árvore-B, ou ser o negador de um membro = de uma classe de operadores de árvore-B, significando que a comparação do construtor de linha só é possível quando o operador for =, <>, <, <=, > ou >=, ou possuir semântica semelhante a um destes.

Os casos = e <> funcionam um pouco diferente dos outros. Duas linhas são consideradas iguais se todos os seus membros correspondentes forem não nulos e iguais; as linhas são diferentes se algum membro correspondente for não nulo e diferente; senão, o resultado da comparação de linhas será desconhecido (nulo).

Para os casos <, <=, > e >=, os elementos da linha são comparados da esquerda para a direita, parando assim que for encontrado um par de elementos diferentes ou nulo. Se um destes pares de elementos for nulo, o resultado da comparação de linha será desconhecido (nulo); senão, a comparação deste par de elementos determinará o resultado. Por exemplo, ROW(1,2,NULL) < ROW(1,3,0) resulta em verdade, e não em nulo, porque o terceiro par de elementos não é considerado.

construtor_de_linha IS DISTINCT FROM construtor_de_linha

Esta construção é semelhante a uma comparação de linha <>, mas não produz nulo para entradas nulas. Em vez disso, qualquer valor nulo é considerado diferente de (distinto de) qualquer valor não nulo, e quaisquer dois nulos são considerados iguais (não distintos). Assim, o resultado será sempre verdade ou falso, e nunca nulo.

construtor_de_linha IS NOT DISTINCT FROM construtor_de_linha

Esta construção é semelhante a uma comparação de linha =, mas não produz nulo para entradas nulas. Em vez disso, qualquer valor nulo é considerado diferente de (distinto de) qualquer valor não nulo, e quaisquer dois nulos são considerados iguais (não distintos). Assim, o resultado será sempre verdade ou falso, e nunca nulo.

9.25.6. Comparação de tipo de dados composto #

record operador record

A especificação do padrão SQL requer que a comparação de linha retorne nulo se o resultado depender da comparação de dois valores nulos, ou de um nulo e um não nulo. O PostgreSQL faz isto apenas ao comparar os resultados de dois construtores de linha (como na Seção 9.25.5), ou quando compara um construtor de linha com a saída de uma subconsulta (como na Seção 9.24). Em outros contextos onde dois valores de tipo de dados composto são comparados, dois valores de campo nulos são considerados iguais, e um nulo é considerado maior que um não nulo. Isso é necessário para obter um comportamento consistente de classificação e indexação para os tipos de dados compostos.

Cada lado é avaliado, e comparados linha por linha. As comparações de tipo de dados composto são permitidas quando o operador é =, <>, <, <=, > ou >=, ou tem semântica semelhante a um desses. (Sendo específico, um operador pode ser um operador de comparação de linhas se for membro de uma classe de operadores de árvore-B, ou se for o negador do membro = de uma classe de operadores de árvore-B.) O comportamento padrão dos operadores acima é idêntico a IS [ NOT ] DISTINCT FROM para construtores de linha (veja a Seção 9.25.5).

Para dar suporte à correspondência de linhas que incluem elementos sem uma classe de operadores de árvore-B padrão, são definidos os seguintes operadores para comparação de tipo de dados composto: *=, *<>, *<, *<=, *> e *>=. Estes operadores comparam a representação binária interna das duas linhas. Duas linhas podem ter uma representação binária diferente, mesmo que as comparações das duas linhas com o operador de igualdade sejam verdadeiras. A ordenação das linhas nesses operadores de comparação é determinística, mas não significativa. Estes operadores são usados internamente para visões materializadas, podendo ser úteis para outras finalidades especializadas, como replicação e deduplicação de árvore-B (veja a Seção 65.1.4.3). Entretanto, geralmente não se destinam a ser úteis para escrever consultas.