PostgreSQL
 sql >> Base de Dados >  >> RDS >> PostgreSQL

Armazenar consulta comum como coluna?


Existe uma maneira de armazenar essa sub-seleção como uma pseudo-coluna na tabela?

Uma VIEW como foi aconselhado é uma solução perfeitamente válida. Vá em frente.

Mas há outra maneira que se encaixa ainda mais na sua pergunta. Você pode escrever uma função que use o tipo de tabela como parâmetro para emular um "campo calculado" ou "coluna gerada" .

Considere este caso de teste, derivado de sua descrição:
CREATE TABLE tbl_a (a_id int, col1 int, col2 int);
INSERT INTO tbl_a VALUES (1,1,1), (2,2,2), (3,3,3), (4,4,4);

CREATE TABLE tbl_b (b_id int, a_id int, colx int);
INSERT INTO tbl_b VALUES
  (1,1,5),  (2,1,5),  (3,1,1)
, (4,2,8),  (5,2,8),  (6,2,6)
, (7,3,11), (8,3,11), (9,3,11);

Criar função que emula col3 :
CREATE FUNCTION col3(tbl_a)
  RETURNS int8
  LANGUAGE sql STABLE AS
$func$
SELECT sum(colx)
FROM   tbl_b b
WHERE  b.a_id = $1.a_id
$func$;

Agora você pode consultar:
SELECT a_id, col1, col2, tbl_a.col3
FROM   tbl_a;

Ou ainda:
SELECT *, a.col3 FROM tbl_a a;

Observe como escrevi tbl_a.col3 / a.col3 , não apenas col3 . Isso é essencial .

Ao contrário de uma "coluna virtual" no Oracle, não incluído automaticamente em um SELECT * FROM tbl_a . Você pode usar um VIEW por isso.

Por que isso funciona?


A maneira comum de fazer referência a uma coluna de tabela é com notação de atributo :
SELECT tbl_a.col1 FROM tbl_a;

A maneira comum de chamar uma função é com notação funcional :
SELECT col3(tbl_a);

Geralmente, é melhor manter essas formas canônicas , que concordam com o padrão SQL.

Mas o Postgres também permite a notação de atributos. Estes também funcionam:
SELECT col1(tbl_a) FROM tbl_a;
SELECT tbl_a.col3;

Mais sobre isso no manual.
Você provavelmente já viu onde isso está indo. Este parece como se você adicionasse uma coluna extra da tabela tbl_a enquanto col3() é na verdade uma função que pega a linha atual de tbl_a (ou seu alias) como argumento de tipo de linha e calcula um valor.
SELECT *, a.col3
FROM   tbl_a AS a;

Se houver uma coluna real col3 tem prioridade e o sistema não procura uma função com esse nome pegando a linha tbl_a como parâmetro.

A "beleza" disso:você pode adicionar ou remover colunas de tbl_a e a última consulta retornará dinamicamente todas as colunas atuais, onde uma exibição retornaria apenas as colunas que existiam no momento da criação (ligação inicial vs. ligação tardia de * ).
Claro, você tem que descartar a função dependente antes de poder descartar a tabela agora. E você deve tomar cuidado para não invalidar a função ao fazer alterações na tabela.

Eu ainda não usaria. É muito surpreendente para o leitor inocente.