5.4. Colunas geradas #

Uma coluna gerada é uma coluna especial, sempre calculada a partir de outras colunas. Assim, está para as colunas o que uma visão está para as tabelas. Existem dois tipos de colunas geradas: armazenadas e virtuais. Uma coluna gerada armazenada é computada quando é escrita (inserida ou atualizada), e ocupa o espaço de armazenamento como se fosse uma coluna normal. Uma coluna gerada virtual não ocupa espaço de armazenamento, sendo computada quando é lida. Assim, uma coluna gerada virtual equivale a uma visão, e uma coluna gerada armazenada é semelhante a uma visão materializada (exceto por ser atualizada automaticamente).

Para criar uma coluna gerada, deve ser usada a cláusula GENERATED ALWAYS AS do comando CREATE TABLE, como, por exemplo:

CREATE TABLE pessoa (
    ...,
    altura_cm numeric,
    altura_pol numeric GENERATED ALWAYS AS (height_cm / 2.54)
);

Uma coluna gerada é, por padrão, do tipo virtual. Deve ser usada uma das palavras-chave VIRTUAL ou STORED para tornar a escolha explícita. Veja CREATE TABLE para obter mais detalhes.

Uma coluna gerada não pode receber valor diretamente. Nos comandos INSERT e UPDATE não é possível especificar um valor para uma coluna gerada, mas pode ser especificada a palavra-chave DEFAULT.

Vejamos as diferenças entre uma coluna com valor padrão e uma coluna gerada. O valor padrão da coluna é avaliado só uma vez quando a linha é inserida pela primeira vez, se nenhum outro valor for fornecido; uma coluna gerada é atualizada sempre que a linha é alterada e não pode ser mudada. Um valor padrão de coluna não pode se referir a outras colunas da tabela; uma expressão de geração normalmente faria isso. Um valor padrão de coluna pode usar funções voláteis como, por exemplo, random(), ou funções referentes à hora corrente; isso não é permitido para as colunas geradas.

Várias restrições se aplicam à definição de colunas geradas e tabelas envolvendo colunas geradas:

Considerações adicionais se aplicam ao uso de colunas geradas.

Exemplo 5.1. Exemplo do tradutor

Complementado o exemplo das colunas de identidade visto no tópico anterior com o exemplo deste tópico teremos:

DROP TABLE pessoa;
CREATE TABLE pessoa (
    id         bigint GENERATED BY DEFAULT AS IDENTITY,
    nome       text,
    endereço   text,
    altura_cm  numeric,
    altura_pol numeric GENERATED ALWAYS AS (altura_cm / 2.54) STORED
);
INSERT INTO pessoa (nome, endereço, altura_cm) VALUES ('A', 'foo', 150);
INSERT INTO pessoa (nome, endereço, altura_cm) VALUES ('B', 'bar', 160);
INSERT INTO pessoa (id, nome, endereço, altura_cm) VALUES (DEFAULT, 'C', 'baz', 170);
INSERT INTO pessoa (id, nome, endereço, altura_cm) VALUES (4, 'D', 'bax', 175);
INSERT INTO pessoa VALUES (DEFAULT, 'E', 'baz', 180, DEFAULT);
SELECT * FROM pessoa;

 id | nome | endereço | altura_cm |     altura_pol
----+------+----------+-----------+---------------------
  1 | A    | foo      |       150 | 59.0551181102362205
  2 | B    | bar      |       160 | 62.9921259842519685
  3 | C    | baz      |       170 | 66.9291338582677165
  4 | D    | bax      |       175 | 68.8976377952755906
  4 | E    | baz      |       180 | 70.8661417322834646
(5 linhas)