Eu sei que isso foi perguntado várias vezes no passado, desculpe pela repetição, estou apenas tentando pensar em uma solução.
Estou procurando uma maneira de consultar uma tabela excluindo uma pequena minoria das colunas sem ter que consultar o information_schema manualmente todas as vezes (uma vez que muitas das minhas tabelas consistem em 50 ou mais colunas, apenas 2-3 das quais são usadas para coisas que são irrelevantes no caso de uso desejado.)
Eu fiz isso assim:
query 1 retorna a lista de todas as colunas que existem em uma tabela menos as que você não deseja.
CREATE OR REPLACE FUNCTION public.inverse_columns(
_table_name text DEFAULT NULL::text,
_col_list text[] DEFAULT NULL::text[])
RETURNS text[] AS
$BODY$
DECLARE
col_arr text[];
BEGIN
EXECUTE 'SELECT array_agg(column_name::text) FROM information_schema.columns
WHERE table_name = ' ||quote_literal(_table_name) ||' AND
column_name NOT IN
('||chr(39)|| array_to_string(_col_list, quote_literal(chr(44)))||chr(39)||');'
INTO col_arr;
RETURN col_arr;
END;
$BODY$
LANGUAGE plpgsql IMMUTABLE
COST 100;
ALTER FUNCTION public.inverse_columns(text, text[])
OWNER TO postgres;
enquanto a consulta dois usa a matriz de saída em outra consulta dinâmica para retornar o conjunto de resultados.
CREATE OR REPLACE FUNCTION public.except_select(
_table_name text DEFAULT NULL::text,
_col_list text[] DEFAULT NULL::text[])
RETURNS SETOF record AS
$BODY$
DECLARE
ret_cols text[] := inverse_columns(_table_name, _col_list);
ret_vals record;
BEGIN
RETURN QUERY
EXECUTE 'SELECT '|| quote_literal(array_to_string(ret_cols, chr(44)||chr(32))) ||
'FROM ' || _table_name||';';
END;
$BODY$
LANGUAGE plpgsql IMMUTABLE
COST 100;
ALTER FUNCTION public.except_select(text, text[])
OWNER TO postgres;
o erro que estou recebendo é esse:
ERROR: a column definition list is required for functions returning "record"
LINE 1: SELECT * FROM except_select.....
e embora eu entenda que estou usando mal o registro, não consigo pensar em uma boa maneira de retornar um conjunto indefinido de linhas sem retornar um refcursor e usá-lo para preencher um conjunto de resultados (que é o que estou trabalhando direito agora com progresso lento, a menos que eu possa ter uma ideia melhor de como fazer isso.)
EDIT:
few days of playing around with it and I gave up.
No SQL, não é possível ter uma função que descubra simultaneamente quais colunas ela deve retornar e as retorne.
É uma consequência da regra fundamental de que a estrutura de saída de uma consulta SQL deve ser conhecida ao analisar uma consulta, antes de executá-la .
Se o lado do cliente cooperar, isso não é um problema. Basta implementar um processo de duas etapas:
passo 1: chamada
inverse_columns()
que retorna a instrução SELECT como uma string (ou apenas a lista de colunas e seu código cliente constrói o restante da instrução).passo #2: execute a instrução SELECT.
Não há nenhum processo manual envolvido se você puder fazer a automação do lado do cliente.
Por exemplo, as versões mais recentes do psql (9.6) têm uma
\gexec
função que executa uma consulta e reinjeta o resultado como uma consulta SQL.Retrabalhando um pouco sua
except_select
função para retornar uma consulta em vez de uma função:Digamos que queremos consultar tudo ,
pg_stat_activity
exceto oquery
campo, isso pode ser escrito em psql como:Resultado com exibição expandida (\x):