4.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, como novos valores das colunas nos comandos INSERT e UPDATE, e na condição de procura em vários comandos. Algumas vezes o resultado de uma expressão de valor é chamado de escalar, para distingui-lo 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 mesmo 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:

Em acréscimo a esta lista, existem diversas construções que podem ser classificadas como uma expressão, mas que não seguem qualquer regra geral de sintaxe. Possuem, normalmente, a semântica de uma função ou de um operador, sendo explicadas no local apropriado no Capítulo 9. Um exemplo é a cláusula IS NULL.

As constantes já foram mostradas na Seção 4.1.2. As próximas seções discutem as demais opções.

4.2.1. Referências a coluna

Uma coluna pode ser referenciada usando a forma

correlação.nome_da_coluna

onde correlação é o nome de uma tabela (possivelmente qualificado pelo nome do esquema), ou um aliás para a tabela definido por meio da cláusula FROM, ou uma das 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 da correlação e o ponto separador podem ser omitidos, se o nome da coluna for único entre todas as tabelas utilizadas no comando corrente (Consulte também o Capítulo 7).

4.2.2. Parâmetros posicionais

É utilizada uma referência a um parâmetro posicional para indicar um valor fornecido externamente para um comando SQL. Os parâmetros são utilizados nas definições de funções SQL e em comandos preparados. Algumas bibliotecas cliente também suportam a especificação de valores de dados separado da cadeia do comando SQL e, nestes casos, os parâmetros são utilizados para fazer referência a valores de dados fora de linha. 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 nome = $1 $$
    LANGUAGE SQL;

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

4.2.3. Índices

Se uma expressão produzir um valor do tipo matriz, então um elemento específico do valor matricial pode ser extraído escrevendo:

expressão[índice]

e vários elementos adjacentes (uma "fatia da matriz") pode ser extraída escrevendo:

expressão[índice_inferior:índice_superior]

(Neste caso, os colchetes [ ] devem aparecer literalmente). Cada índice é por si só uma expressão, que deve produzir um valor inteiro.

Geralmente a expressão matricial deve estar entre parênteses, mas os parênteses podem ser omitidos quando a expressão a ser indexada é apenas a referência a uma coluna ou um parâmetro posicional. Podem ser concatenados vários índices quando a matriz original for multidimensional. Por exemplo:

minha_tabela.matriz_coluna[4]
minha_tabela.matriz_duas_dim[17][34]
$1[10:42]
(funcao_matriz(a,b))[42]

No último exemplo os parênteses são requeridos. Consulte a Seção 8.10 para obter informações adicionais sobre matrizes.

4.2.4. Escolha de campo

Se uma expressão produzir um valor do tipo composto (tipo linha), então pode-se extrair um campo específico da linha escrevendo:

expressão.nome_do_campo

Geralmente a expressão de linha deve estar entre parênteses, mas os parênteses podem ser omitidos quando a expressão de seleção for apenas uma referência a tabela ou um parâmetro posicional. Por exemplo,

minha_tabela.minha_coluna
$1.alguma_coluna
(funcao_de_linha(a,b)).col3

(Portanto, uma referência a coluna qualificada é, na verdade, apenas um caso especial da sintaxe de seleção de campo).

4.2.5. Chamadas de operador

Existem três sintaxes possíveis para 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 símbolo operador segue as regras de sintaxe da Seção 4.1.3, ou é uma das palavras chave AND, OR ou NOT, ou é um nome de operador qualificado na forma:
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 9 descreve os operadores nativos. [1] [2] [3]

4.2.6. Chamadas de função

A sintaxe para chamada de função é o nome da função (possivelmente qualificado pelo nome do esquema), seguido 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 9. Podem ser adicionadas outras funções pelo usuário.

4.2.7. 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 pela consulta. Uma função de agregação reduz vários valores de entrada a um único valor de saída, tal como a soma ou a média dos valores entrados. 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 nome_da_agregação é uma agregação definida anteriormente (possivelmente qualificado pelo nome do esquema), 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 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; como 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(f1) retorna o número de linhas de entrada onde f1 não é nulo; count(distinct f1) retorna o número de valores distintos não nulos de f1.

As funções de agregação predefinidas estão descritas na Seção 9.15. Podem ser adicionadas pelo usuário outras funções de agregação.

Uma expressão de agregação pode aparecer apenas na lista de resultados ou na cláusula HAVING do comando SELECT. Seu uso é proibido nas outras cláusulas, tal como WHERE, porque estas cláusulas são avaliadas logicamente antes dos resultados das agregações estarem formados.

Quando uma expressão de agregação aparece em uma subconsulta (consulte a Seção 4.2.9 e a Seção 9.16), normalmente a agregação é avaliada a partir das linhas da subconsulta. Porém ocorre uma exceção quando o argumento da agregação contém apenas variáveis do nível externo: a agregação então pertence ao nível externo mais próximo, sendo avaliada a partir das linhas desta consulta. A expressão de agregação como um todo é, então, uma referência externa para a subconsulta onde aparece, agindo como uma constante em qualquer avaliação da subconsulta. A restrição de aparecer apenas na lista de resultados ou na cláusula HAVING se aplica com respeito ao nível da consulta que a agregação pertence.

4.2.8. Conversões de tipo

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

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

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

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

Geralmente a conversã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ída a uma coluna de tabela); o sistema aplica automaticamente a conversão de tipo nestes casos. Entretanto, a conversão automática de tipo é feita apenas para as conversões marcadas nos catálogos do sistema como "OK para aplicar implicitamente". As outras conversões devem ser chamadas por meio da sintaxe de conversão explícita. Esta restrição tem por finalidade impedir que aconteçam conversões surpreendentes aplicadas em silêncio.

Também é possível especificar uma conversão de tipo 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 de conversão na forma de função pode ocasionar inconsistências, devendo ser evitada em novos aplicativos. (A sintaxe tipo chamada de função é, de fato, apenas uma chamada de função. Quando é utilizada uma das duas sintaxes padrão de conversão para fazer conversão em tempo de execução, internamente chama a função registrada para realizar esta conversão. Por convenção, estas funções de conversão possuem o mesmo nome de seu tipo de dado de saída e, portanto, a "sintaxe tipo função" não é nada mais do que a chamada direta à função de conversão subjacente. Como é óbvio, isto não é algo que um aplicativo portável possa depender).

4.2.9. Subconsultas escalares

Uma subconsulta escalar é um comando SELECT comum, entre parênteses, que retorna exatamente uma linha com uma coluna (consulte o Capítulo 7 para obter informações sobre como escrever consultas). O comando SELECT é executado e o único valor retornado é utilizado na expressão de valor envoltória. É 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 envoltória, as quais atuam como constantes durante a avaliação da subconsulta. Veja, também, outras expressões envolvendo subconsultas na Seção 9.16. [4]

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

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

4.2.10. Construtores de matriz

Um construtor de matriz é uma expressão que constrói um valor matriz a partir dos valores de seus elementos membros. Um construtor de matriz simples é composto pela palavra chave ARRAY, um abre colchetes [, uma ou mais expressões (separadas por vírgula) para os valores dos elementos da matriz e, finalmente, um fecha colchetes ]. Por exemplo,

SELECT ARRAY[1,2,3+4];

  array
---------
 {1,2,7}
(1 linha)

O tipo de dado do elemento da matriz é o tipo comum das expressões membro, determinado utilizando as mesmas regras das construções UNION e CASE (consulte a Seção 10.5).

Os valores matriz multidimensional podem ser construídos aninhando construtores de matriz. Nos construtores internos, a palavra chave ARRAY pode ser omitida. Por exemplo, estes dois comandos produzem o mesmo resultado:

SELECT ARRAY[ARRAY[1,2], ARRAY[3,4]];

     array
---------------
 {{1,2},{3,4}}
(1 linha)

SELECT ARRAY[[1,2],[3,4]];

     array
---------------
 {{1,2},{3,4}}
(1 linha)

Uma vez que as matrizes multidimensionais devem ser retangulares, os construtores internos no mesmo nível devem produzir submatrizes com dimensões idênticas.

Os elementos construtores de matriz multidimensional podem ser qualquer coisa que produza uma matriz do tipo apropriado, e não apenas uma construção sub-ARRAY. Por exemplo:

CREATE TABLE arr(f1 int[], f2 int[]);

INSERT INTO arr VALUES (ARRAY[[1,2],[3,4]], ARRAY[[5,6],[7,8]]);

SELECT ARRAY[f1, f2, '{{9,10},{11,12}}'::int[]] FROM arr;

                     array
------------------------------------------------
 {{{1,2},{3,4}},{{5,6},{7,8}},{{9,10},{11,12}}}
(1 linha)

Também é possível construir uma matriz a partir do resultado de uma subconsulta. Nesta forma, o construtor de matriz é escrito com a palavra chave ARRAY seguida por uma subconsulta entre parênteses, e não entre colchetes. Por exemplo:

SELECT ARRAY(SELECT oid FROM pg_proc WHERE proname LIKE 'bytea%');

                          ?column?
-------------------------------------------------------------
 {2011,1954,1948,1952,1951,1244,1950,2005,1949,1953,2006,31}
(1 linha)

A subconsulta deve retornar uma única coluna. A matriz unidimensional produzida terá um elemento para cada linha no resultado da subconsulta, com o tipo do elemento correspondendo ao da coluna de saída da subconsulta.

O índice de um valor da matriz construído com ARRAY sempre começa por um. Para obter informações adicionais sobre matrizes consulte a Seção 8.10.

4.2.11. Construtores de linha

Um construtor de linha é uma expressão que constrói um valor linha (também chamado de valor composto) a partir de valores de seus campos membros. Um construtor de linha é formado pela palavra chave ROW, um abre parênteses, zero ou mais expressões (separadas por vírgula) para os valores dos campos da linha e, finalmente, por um fecha parênteses. Por exemplo:

SELECT ROW(1,2.5,'isto é um teste');

A palavra chave ROW é opcional quando existe mais de uma expressão na lista.

Por padrão, o valor criado através da expressão ROW é de um tipo de registro anônimo. Se for necessário, pode ser convertido para um tipo composto com nome — tanto o tipo de linha de uma tabela, ou um tipo composto criado pelo comando CREATE TYPE AS. Pode ser necessária uma conversão explícita para evitar ambigüidade. Por exemplo:

CREATE TABLE minha_tabela(f1 int, f2 float, f3 text);

CREATE FUNCTION getf1(minha_tabela) RETURNS int AS 'SELECT $1.f1' LANGUAGE SQL;

-- Não é necessária nenhuma conversão, porque só existe uma getf1()
SELECT getf1(ROW(1,2.5,'isto é um teste'));

 getf1
-------
     1
(1 linha)

CREATE TYPE meu_tipo_de_linha AS (f1 int, f2 text, f3 numeric);

CREATE FUNCTION getf1(meu_tipo_de_linha) RETURNS int AS 'SELECT $1.f1' LANGUAGE SQL;

-- Agora é necessária uma conversão para indicar a função a ser chamada:
SELECT getf1(ROW(1,2.5,'isto é um teste'));
ERRO:  a função getf1(record) não é única

SELECT getf1(ROW(1,2.5,'isto é um teste')::minha_tabela);

 getf1
-------
     1
(1 linha)

SELECT getf1(CAST(ROW(11,'isto é um teste',2.5) AS meu_tipo_de_linha));

 getf1
-------
    11
(1 linha)

Os construtores de linha podem ser utilizados para construir valores compostos a serem armazenados em colunas de tabelas de tipo composto, ou serem passados para funções que recebem parâmetros compostos. Também é possível comparar dois valores linha ou testar uma linha com IS NULL ou IS NOT NULL como, por exemplo:

SELECT ROW(1,2.5,'isto é um teste') = ROW(1, 3, 'não é o mesmo');

SELECT ROW(a, b, c) IS NOT NULL FROM tabela;

Para obter informações adicionais consulte a Seção 9.17. Os construtores de linha também podem ser utilizados conectados a subconsultas conforme mostrado na Seção 9.16.

4.2.12. Regras para avaliação de expressão

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

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

SELECT true OR alguma_funcao();

então alguma_funcao() não será (provavelmente) chamada. Este é o mesmo caso de quando é escrito

SELECT alguma_funcao() OR true;

Deve ser observado que isto não é o mesmo que os "curtos circuitos" esquerda para direita de 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 obrigar a ordem de avaliação, pode ser utilizada uma construção CASE (consulte a Seção 9.13). 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 for necessário (Neste exemplo em particular, sem dúvida seria melhor evitar o problema escrevendo y > 1.5*x).

Notas

[1]

binary infix operator — foi traduzido como "operador binário-intermediário", mas poderia ter sido traduzido como "operador binário infixo", onde infixo significa "afixo no meio de uma palavra", mas é um termo pouco conhecido. PRIBERAM - Língua Portuguesa On-Line. (N. do T.)

[2]

unary prefix operator — foi traduzido como "operador unário-esquerdo". (N. do T.)

[3]

unary postfix operator — foi traduzido como "operador unário-direito". (N. do T.)

[4]

Oracle — Uma expressão de subconsulta escalar é uma subconsulta que retorna exatamente o valor de uma coluna de uma linha. O valor da expressão de subconsulta escalar é o valor do item da lista de seleção da subconsulta. Se a subconsulta retornar 0 linhas, então o valor da expressão de subconsulta escalar será nulo. Se a subconsulta retornar mais de uma linha, então o Oracle retornará um erro. A expressão de subconsulta escalar pode ser utilizada na maioria das das sintaxes que chamam uma expressão. Entretanto, as subconsultas escalares não são expressões válidas nos seguintes lugares: Como valor padrão para colunas; Como expressões de hash para clusters; Como a cláusula RETURNING dos comandos da DM; Como a base de um índice baseado em função; Nas restrições CHECK; Nas condições WHEN das expressões CASE; Nas cláusulas GROUP BY e HAVING; Nas cláusulas START WITH e CONNECT BY; Nos comandos que não estão relacionados com consultas, como o CREATE PROFILE; Oracle® Database SQL Reference 10g Release 1 (10.1) Part Number B10759-01 (N. do T.)

SourceForge.net Logo CSS válido!