Solução para o caso simples
Conforme explicado nas respostas referenciadas abaixo, você pode usar tipos registrados (linha) e, assim, declarar implicitamente o tipo de retorno de uma função polimórfica:
CREATE OR REPLACE FUNCTION public.get_table(_tbl_type anyelement)
RETURNS SETOF anyelement AS
$func$
BEGIN
RETURN QUERY EXECUTE format('TABLE %s', pg_typeof(_tbl_type));
END
$func$ LANGUAGE plpgsql;
Ligar:
SELECT * FROM public.get_table(NULL::public.users); -- note the syntax!
Retorna a tabela completa (com todas as colunas do usuário).
Espere! Como?
Explicação detalhada nesta resposta relacionada, capítulo"Vários tipos de tabela completa" :
- Refatorar uma função PL/pgSQL para retornar a saída de várias consultas SELECT
TABLE foo
é a abreviação de SELECT * FROM foo
:- Existe um atalho para SELECT * FROM?
2 passos para o tipo de retorno completamente dinâmico
Mas o que você está tentando fazer é estritamente impossível em um único Comando SQL.
Quero passarschema_name
etable_name
como parâmetros para funcionar e obter a lista de registros, de acordo comcolumn_visible
campo empublic.fields
tabela.
Não há uma maneira direta de retornar uma seleção arbitrária de colunas (tipo de retorno não conhecido no momento da chamada) de uma função - ou qualquer Comando SQL. O SQL exige saber número, nomes e tipos de colunas resultantes no momento da chamada. Mais no 2º capítulo desta resposta relacionada:
- Como gerar um CROSS JOIN dinâmico onde a definição da tabela resultante é desconhecida?
Existem várias soluções alternativas . Você pode envolver o resultado em um dos tipos de documento padrão (
json
, jsonb
, hstore
, xml
). Ou você gera a consulta com uma chamada de função e executa o resultado com a próxima:
CREATE OR REPLACE FUNCTION public.generate_get_table(_schema_name text, _table_name text)
RETURNS text AS
$func$
SELECT format('SELECT %s FROM %I.%I'
, string_agg(quote_ident(column_name), ', ')
, schema_name
, table_name)
FROM fields
WHERE column_visible
AND schema_name = _schema_name
AND table_name = _table_name
GROUP BY schema_name, table_name
ORDER BY schema_name, table_name;
$func$ LANGUAGE sql;
Ligar:
SELECT public.generate_get_table('public', 'users');
Isso cria uma consulta do formulário:
SELECT usr_id, usr FROM public.users;
Execute-o na 2ª etapa. (Você pode querer adicionar números de coluna e ordenar colunas.)
Ou anexe
\gexec
no psql para executar o valor de retorno imediatamente. Ver:Como forçar a avaliação da subconsulta antes de ingressar/enviar para servidor externo
Certifique-se de se defender contra injeção de SQL:
- INSERIR com o nome da tabela dinâmica na função de gatilho
- Definir nomes de tabelas e colunas como argumentos em uma função plpgsql?
varchar(100)
não faz muito sentido para identificadores, que são limitados a 63 caracteres no Postgres padrão:- Máximo de caracteres em rótulos (nomes de tabelas, colunas, etc.)
Se você entender como o tipo de identificador de objeto
regclass
funciona, você pode substituir o esquema e o nome da tabela por um único regclass
coluna.