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

Função plpgsql:Retorna linhas de uma visão criada a partir de uma tabela aleatória


Poderia funcionar assim:
CREATE OR REPLACE FUNCTION tt_query(orig_name regclass, data_tt timestamp)
  RETURNS SETOF record AS
$func$
BEGIN

EXECUTE 'CREATE OR REPLACE TEMP VIEW tmp as 
select * 
from  '
|| orig_name 
|| ' where trigger_changed >'
|| quote_literal(data_tt)
|| ' ORDER BY trigger_changed DESC';

-- other work on view tmp

-- return the rows of view temp
RETURN QUERY
SELECT * FROM tmp;

END
$func$  LANGUAGE plpgsql;

  • Observe o uso do tipo de identificador de objeto regclass para evitar automaticamente a injeção de SQL.

  • Não use a sintaxe desatualizada var ALIAS for $1 se você não precisa. Em vez disso, declare nomes de parâmetros.

  • Eu não usaria a palavra-chave temp como identificador, mesmo que isso seja permitido. Usando tmp em vez de.

  • Use RETURN QUERY para retornar um conjunto de registros. Isso pode até ser uma chamada estática sem EXECUTE . No entanto, você está retornando registros anônimos e o Postgres exige uma lista de definição de coluna a cada chamada:
SELECT * FROM tt_query('tbl_name', '2014-02-15 12:00')
AS f(col1 int, col2 text, ...);

Isso é bastante complicado.

Melhores soluções


Se você sabe o tipo de retorno (mesmo que os nomes das tabelas estejam mudando, a lista de colunas pode compartilhar os mesmos tipos), declare-o no momento da criação. Considere esta pergunta relacionada:
PostgreSQL:ERRO:42601:uma lista de definição de coluna é necessária para funções que retornam "registro"

Se o tipo de retorno variar com o nome da tabela fornecida, ainda há uma solução muito melhor. Como você está criando uma visão com SELECT * FROM tbl , você pode utilizar o tipo conhecido da própria tabela como polimórfico parâmetro:
CREATE OR REPLACE FUNCTION tt_query(orig_name anyelement, data_tt timestamp)
  RETURNS SETOF anyelement AS
$func$
BEGIN

EXECUTE format('CREATE OR REPLACE TEMP VIEW tmp AS
   SELECT * FROM  %s
   WHERE  trigger_changed > %L
   ORDER  BY trigger_changed DESC'
  ,pg_typeof(orig_name)
  ,data_tt);

-- other work on view tmp

-- return the rows of view tmp
RETURN QUERY
SELECT * FROM tmp;

END
$func$  LANGUAGE plpgsql;

Chamada simplificada:
SELECT * FROM tt_query(NULL::tbl_name, '2014-02-15 12:00');

Também usando format() para concatenação de strings simples e segura.

Mais detalhes nesta resposta relacionada:
Refatorar uma função PL/pgSQL para retornar a saída de várias consultas SELECT