1.2. Expressões de valor

As expressões de valor são utilizadas em diversos contextos, como na lista de seleção do comando SELECT, nos valores das colunas nos comandos INSERT e UPDATE, e na condição de pesquisa em vários comandos. O resultado de uma expressão de valor é algumas vezes chamado de escalar, para distinguir do resultado de uma expressão de tabela (que é uma tabela). As expressões de valor são, portanto, chamadas também de expressões escalares (ou pura e simplesmente de expressões). A sintaxe da expressão permite o cálculo de valores a partir de partes primitivas utilizando operações aritméticas, lógicas, de conjunto e outras.

A expressão de valor é uma das seguintes:

Devem ser acrescentadas a esta lista diversas construções que podem ser classificadas como expressão, mas que não seguem as regras gerais de sintaxe. Possuem, normalmente, a semântica de uma função ou de um operador, sendo explicadas no local apropriado no Capítulo 6. Um exemplo é a cláusula IS NULL.

As constantes já foram discutidas na Seção 1.1.2. As seções abaixo discutem as demais opções.

1.2.1. Referências a colunas

Uma coluna pode ser referenciada usando a forma

correlação.nome_da_coluna

ou a forma

correlação.nome_da_coluna[índice]

(Neste caso, os colchetes [] devem ser escritos literalmente)

onde correlação é o nome (possivelmente qualificado) de uma tabela, ou um aliás para a tabela definido na cláusula FROM, ou ainda as palavras chave NEW ou OLD (NEW e OLD somente podem aparecer nas regras de reescrita, enquanto os outros nomes de correlação podem ser usados em qualquer declaração SQL). O nome de correlação e o ponto separador podem ser omitidos se o nome da coluna for único entre todas as tabelas utilizadas pela consulta corrente. (Veja o Capítulo 4.)

Se a coluna for do tipo matriz (array), então o índice opcional seleciona um elemento específico ou elementos da matriz. Se nenhum índice for fornecido, então toda a matriz é selecionada (veja a Seção 5.12 para obter mais informações relativas às matrizes).

1.2.2. Parâmetros posicionais

Uma referência a um parâmetro posicional é utilizada para indicar o parâmetro fornecido externamente a uma declaração SQL. Os parâmetros são utilizados nas definições das funções SQL e nas consultas preparadas. A forma de fazer referência a um parâmetro é:

$número

Por exemplo, considere a definição da função dept como sendo

CREATE FUNCTION dept(text) RETURNS dept
    AS 'SELECT * FROM dept WHERE name = $1'
    LANGUAGE SQL;

Neste caso $1 será substituído pelo primeiro argumento da função quando a função for chamada.

1.2.3. Chamadas de operador

Existem três sintaxes possíveis para a chamada de operador:

expressão operador expressão (operador binário intermediário)
operador expressão (operador unário esquerdo)
expressão operador (operador unário direito)

onde o termo operador segue as regras de sintaxe da Seção 1.1.3, ou é uma das palavras chave AND, OR ou NOT, ou é um nome de operador qualificado

OPERATOR(esquema.nome_do_operador)

Quais são os operadores existentes, e se são unários ou binários, depende de quais operadores foram definidos pelo sistema e pelo usuário. O Capítulo 6 descreve os operadores nativos.

1.2.4. Chamadas de funções

A sintaxe de uma chamada de função é o nome da função (possivelmente qualificado pelo nome do esquema), seguida por sua lista de argumentos entre parênteses:

função ([expressão [, expressão ... ]] )

Por exemplo, a função abaixo calcula a raiz quadrada de 2:

sqrt(2)

A lista de funções nativas está no Capítulo 6. Outras funções podem ser adicionadas pelo usuário.

1.2.5. Funções de agregação

Uma expressão de agregação representa a aplicação de uma função de agregação nas linhas selecionadas por uma consulta. Uma função de agregação transforma vários valores de entrada em um único valor de saída, tal como a soma ou a média. A sintaxe da expressão de agregação é uma das seguintes:

nome_da_agregação (expressão)
nome_da_agregação (ALL expressão)
nome_da_agregação (DISTINCT expressão)
nome_da_agregação ( * )

onde o nome_da_agregação é uma agregação definida previamente (possivelmente um nome qualificado), e expressão é qualquer expressão de valor que não contenha uma expressão de agregação.

A primeira forma de expressão de agregação chama a função de agregação para todas as linhas de entrada onde a expressão fornecida produz um valor não nulo (na verdade, é decisão da função de agregação ignorar ou não os valores nulos --- porém todas as funções padrão o fazem). A segunda forma é idêntica à primeira, porque ALL é o padrão. A terceira forma chama a função de agregação para todos os valores distintos e não nulos da expressão encontrados nas linhas de entrada. A última forma chama a função de agregação uma vez para cada linha de entrada independentemente do valor ser nulo ou não; uma vez que nenhum valor específico de entrada é especificado, geralmente é útil apenas para a função de agregação count().

Por exemplo, count(*) retorna o número total de linhas de entrada; count(campo) retorna o número de linhas de entrada onde campo não é nulo; count(distinct campo) retorna o número de valores distintos e não nulos de campo.

As funções de agregação pré-definidas estão descritas na Seção 6.14. Outras funções de agregação podem ser adicionadas pelo usuário.

1.2.6. Transformação de tipo

Uma transformação de tipo (type cast) especifica a conversão de um tipo de dado em outro. O PostgreSQL aceita duas sintaxes equivalentes para transformação de tipo:

CAST ( expressão AS tipo )
expressão::tipo

A sintaxe CAST está em conformidade com o padrão SQL; a sintaxe com :: é uma utilização histórica do PostgreSQL.

Quando a transformação é aplicada a uma expressão de valor de um tipo conhecido, esta representa uma conversão em tempo de execução. A transformação será bem sucedida apenas se uma função de conversão adequada estiver disponível. Observe que isto é sutilmente diferente da utilização de transformação com constante, conforme mostrado na Seção 1.1.2.4. Uma transformação aplicada a uma cadeia de caracteres sem adornos representa a atribuição inicial do tipo para o valor constante literal e, portanto, será bem sucedida para qualquer tipo (se o conteúdo da cadeia de caracteres possuir uma sintaxe válida para servir de entrada para o tipo de dado).

Geralmente uma transformação explícita de tipo pode ser omitida quando não há ambigüidade em relação ao tipo que a expressão de valor deve produzir (por exemplo, quando é atribuído para coluna de tabela); o sistema aplica automaticamente a transformação de tipo nestes casos. Entretanto, a transformação automática de tipo é feita apenas para as transformações marcadas como "OK para aplicar implicitamente" nos catálogos do sistema. As outras transformações devem ser chamadas por meio da sintaxe de transformação explícita. Esta restrição tem por finalidade prevenir que aconteçam conversões surpreendentes aplicadas silenciosamente.

Também é possível especificar uma transformação utilizando a sintaxe na forma de função:

nome_do_tipo ( expressão )

Entretanto, somente funciona para os tipos cujos nomes também são válidos como nome de função. Por exemplo, double precision não pode ser utilizado desta maneira, mas a forma equivalente float8 pode. Também, os nomes interval, time e timestamp somente podem ser utilizados desta maneira se estiverem entre aspas, devido a conflitos sintáticos. Portanto, o uso da sintaxe na forma de função para transformações pode ocasionar inconsistências devendo ser evitada em novas aplicações. (A sintaxe na forma chamada de função é na verdade apenas a chamada de uma função. Quando uma das duas sintaxes padrão de conversão é utilizada para fazer uma conversão em tempo de execução, internamente é chamada a função registrada para realizar esta conversão. Por convenção, estas funções de conversão possuem o mesmo nome do tipo de dado da saída, mas isto não é algo em que uma aplicação portável deva confiar).

1.2.7. Subconsultas escalares

Uma subconsulta escalar é um comando SELECT comum, entre parênteses, que retorna exatamente uma linha com uma coluna (veja o Capítulo 4 para obter informações sobre como escrever consultas). A consulta SELECT é executada e o único valor retornado é utilizado na expressão. É errado utilizar uma consulta que retorne mais de uma linha ou mais de uma coluna como subconsulta escalar (porém, se durante uma determinada execução a subconsulta não retornar nenhuma linha, não acontece nenhum erro: o resultado escalar é assumido como nulo). A subconsulta pode fazer referência a variáveis da consulta principal, as quais atuam como sendo constantes durante qualquer avaliação da subconsulta. Veja também a Seção 6.15.

Por exemplo, a consulta abaixo retorna a cidade com a maior população de cada estado:

SELECT nome, (SELECT max(populacao) FROM cidades WHERE cidades.estado = estado.nome)
    FROM estados;

1.2.8. Avaliação de expressão

A ordem de avaliação das subexpressões não é definida. Especificamente, as entradas de um operador ou função não são necessariamente avaliadas da esquerda para a direita ou em qualquer outra ordem determinada.

Além disso, se o resultado da expressão puder ser determinado avaliando somente algumas partes da expressão, então as outras subexpressões podem não ser avaliadas. Por exemplo, se for escrito

SELECT true OR alguma_funcao();

então alguma_funcao() não será chamada (provavelmente). O mesmo caso pode acontecer se for escrito

SELECT alguma_funcao() OR true;

Observe que isto não é o mesmo que os "curtos circuitos" esquerda para direita dos operadores booleanos encontrados em algumas linguagens de programação.

Como conseqüência, não é bom utilizar funções com efeitos colaterais como parte de expressões complexas. É particularmente perigoso confiar em efeitos colaterais ou na ordem de avaliação nas cláusulas WHERE e HAVING, porque estas cláusulas são extensamente reprocessadas como parte do desenvolvimento do plano de execução. As expressões booleanas (combinações de AND/OR/NOT) nestas cláusulas podem ser reorganizadas em qualquer forma permitida pelas leis da álgebra booleana.

Quando for essencial estabelecer a ordem de avaliação, uma construção CASE (veja a Seção 6.12) pode ser utilizada. Por exemplo, esta é uma forma não confiável para tentar evitar uma divisão por zero na cláusula WHERE:

SELECT ... WHERE x <> 0 AND y/x > 1.5;

Mas esta forma é segura:

SELECT ... WHERE CASE WHEN x <> 0 THEN y/x > 1.5 ELSE false END;

A construção CASE utilizada desta forma impede as tentativas de otimização devendo, portanto, ser utilizada apenas quando necessário.