Declarar variável do tipo de tabela no PL / pgSQL

8

Gostaria de saber se existe uma maneira de declarar uma variável da tabela de tipos no PL / pgSQL para manter os resultados da consulta? Por exemplo, como posso expressar algo como:

q1 = select * from foo;
q2 = select * from bar;
for t1 in q1:
  for t2 in q2:
    -- do something with t1 and t2

Eu olhei para a construção de retorno seguinte, mas isso parece capaz de lidar apenas com valores de retorno.

JRR
fonte
2
PL / SQL => Oracle, PgPL / SQL => PostgreSQL. Com qual deles você está trabalhando?
Mat
@ Mat: É PL / pgSQL , aliás.
Erwin Brandstetter

Respostas:

12

No PostgreSQL , todo nome de tabela serve como nome do tipo para o tipo de linha (também conhecido como tipo composto ) automaticamente - não um tipo de tabela, não existem "tipos de tabela" ou "variáveis ​​de tabela" no Postgres ( mas existem tabelas digitadas ).
Então você pode simplesmente declarar uma variável desse tipo PL/pgSQL.

CREATE FUNCTION foo()
 RETURNS void LANGUAGE plpgsql AS
$func$
DECLARE
  q1 foo;  -- "foo" ...
  q2 bar;  -- ... and "bar" are existing (visible) table names
BEGIN

FOR q1 IN 
   SELECT * from foo
LOOP
   FOR q2 IN 
      SELECT * from bar
   LOOP
       -- do something with q1 and q2
       -- since q1 and q2 are well known types, you can access columns
       -- with attribute notation. Like: q1.col1
   END LOOP;
END LOOP;

END
$func$

Um FORloop funciona com um cursor interno. Também existem cursores explícitos no plpgsql.

Você também pode apenas declarar variáveis ​​do tipo genérico record. Pode levar qualquer tipo de linha na atribuição automaticamente. Mas regras especiais se aplicam. Certifique-se de seguir o link e ler o capítulo do manual!

Embora muitas vezes seja conveniente retornar a função SETOF <table name>, o retorno SETOF recordnão é tão conveniente. O sistema não sabe o que a função retorna dessa maneira e você deve adicionar uma lista de definições de coluna a cada chamada. O que é uma dor. Detalhes sobre as funções da tabela no manual .

Muitas vezes, existem soluções mais eficientes com SQL simples. O loop é uma medida de último recurso, quando você pode fazer as coisas em uma varredura em que precisaria de várias varreduras no SQL puro.

Erwin Brandstetter
fonte
2
Observe também que se você quiser retornar o tipo de tabela que você pode apenas dizer algo comoCREATE FUNCTION footest() RETURNS SETOF foo LANGUAGE PLPGSQL AS $$...
Chris Travers
Por que, então, temos o recurso de "tipos compostos" se podemos criar tabelas, sem restrições aplicadas a tipos compostos (sem restrições, etc.)? A única maneira significativa de usar tipos compostos que vejo é retornar alguns (ou vários) parâmetros de uma função em vez de criar uma tabela inteira para isso.
SaneDeveloper