Тази заявка създава пълния DML оператор, който търсите:
WITH x AS (
SELECT 'public'::text AS _schema -- provide schema name ..
,'somereport'::text AS _tbl -- .. and table name once
)
SELECT 'SELECT ' || string_agg('sum(' || quote_ident(column_name)
|| ') AS sum_' || quote_ident(column_name), ', ')
|| E'\nFROM ' || quote_ident(x._schema) || '.' || quote_ident(x._tbl)
FROM x, information_schema.columns
WHERE table_schema = _schema
AND table_name = _tbl
AND data_type = 'integer'
GROUP BY x._schema, x._tbl;
Можете да го изпълните отделно или да обвиете тази заявка във функция plpgsql и да изпълните заявката автоматично с EXECUTE
:
Пълна автоматизация
Тествано с PostgreSQL 9.1.4
CREATE OR REPLACE FUNCTION f_get_sums(_schema text, _tbl text)
RETURNS TABLE(names text[], sums bigint[]) AS
$BODY$
BEGIN
RETURN QUERY EXECUTE (
SELECT 'SELECT ''{'
|| string_agg(quote_ident(c.column_name), ', ' ORDER BY c.column_name)
|| '}''::text[],
ARRAY['
|| string_agg('sum(' || quote_ident(c.column_name) || ')'
, ', ' ORDER BY c.column_name)
|| ']
FROM '
|| quote_ident(_schema) || '.' || quote_ident(_tbl)
FROM information_schema.columns c
WHERE table_schema = _schema
AND table_name = _tbl
AND data_type = 'integer'
);
END;
$BODY$
LANGUAGE plpgsql;
Обаждане:
SELECT unnest(names) AS name, unnest (sums) AS col_sum
FROM f_get_sums('public', 'somereport');
Връща:
name | col_sum
---------------+---------
int_col1 | 6614
other_int_col | 8364
third_int_col | 2720642
Обяснете
Трудността е да се дефинира RETURN
тип за функцията, докато броят и имената на върнатите колони ще варират. Една подробност, която помага малко:искате само integer
колони.
Реших това, като формирах масив от bigint
(sum(int_col)
връща bigint
). Освен това връщам масив от имена на колони. И двете сортирани по азбучен ред по име на колона.
В извикването на функцията разделих тези масиви с unnest()
стигайки до показания красив формат.
Динамично създадената и изпълнена заявка е нещо за напреднали. Не се обърквайте от множество слоеве цитати. По принцип имате EXECUTE
който приема текстов аргумент, съдържащ SQL заявката за изпълнение. Този текст от своя страна се предоставя от вторична SQL заявка, която изгражда низа на заявката на първичната заявка.
Ако това е твърде много наведнъж или plpgsql
е доста ново за вас, започнете с този свързан отговор
където обяснявам основите, занимавайки се с много по-проста функция и предоставям връзки към ръководството за основните функции.
Ако производителност от съществено значение е директно запитване до каталога на Postgres (pg_catalog.pg_attributes
), вместо да използвате стандартизираните (но бавни) information_schema.columns
. Ето един прост пример с pg_attributes
.