我知道过去曾多次询问过这个问题,很抱歉重复我只是想集思广益解决方案。
我正在寻找一种查询表的方法,同时排除一小部分列,而不必每次都手动查询 information_schema(因为我的很多表都包含 50 或更多列,其中只有 2-3 列用于事物与所需用例无关。)
我这样做是这样的:
查询 1 返回表中存在的所有列减去不需要的列的列表。
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;
而查询二在另一个动态查询中使用输出数组以返回结果集。
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;
我收到的错误是这样的:
ERROR: a column definition list is required for functions returning "record"
LINE 1: SELECT * FROM except_select.....
虽然我明白这是我在滥用记录,但我想不出一个好的方法来返回一组未定义的行,而不是返回一个 refcursor 并使用它来填充结果集(这就是我正在做的事情)现在进展缓慢,除非我能更好地了解如何做到这一点。)
EDIT:
few days of playing around with it and I gave up.
在 SQL 中,不可能有一个函数可以同时计算出它应该返回哪些列并返回它们。
这是基本规则的结果,即在执行查询之前解析查询时必须知道 SQL 查询的输出结构。
如果客户端合作,那不是问题。只需实施一个两步过程:
第 1 步:调用
inverse_columns()
以字符串形式返回 SELECT 语句(或仅返回列列表,您的客户端代码构建语句的其余部分)。步骤 #2:运行 SELECT 语句。
如果您可以进行客户端自动化,则不涉及手动过程。
例如,较新版本的 psql (9.6) 具有
\gexec
执行查询并将结果重新注入为 SQL 查询的功能。稍微修改一下
except_select
函数以返回查询而不是函数:假设我们要查询除字段
pg_stat_activity
之外的所有query
字段,这可以用 psql 编写为:扩展显示 (\x) 的结果: