Deze query creëert de volledige DML-instructie die u zoekt:
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;
U kunt het afzonderlijk uitvoeren of deze query in een plpgsql-functie verpakken en de query automatisch uitvoeren met EXECUTE
:
Volledige automatisering
Getest met 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;
Bel:
SELECT unnest(names) AS name, unnest (sums) AS col_sum
FROM f_get_sums('public', 'somereport');
Retouren:
name | col_sum
---------------+---------
int_col1 | 6614
other_int_col | 8364
third_int_col | 2720642
Uitleggen
De moeilijkheid is om de RETURN
. te definiëren type voor de functie, terwijl het aantal en de namen van de geretourneerde kolommen zal variëren. Een detail dat een beetje helpt:je wilt alleen integer
kolommen.
Ik heb dit opgelost door een array te vormen van bigint
(sum(int_col)
retourneert bigint
). Daarnaast retourneer ik een array met kolomnamen. Beide alfabetisch gesorteerd op kolomnaam.
In de functieaanroep heb ik deze arrays opgesplitst met unnest()
aankomen op het mooie formaat dat wordt weergegeven.
De dynamisch gemaakte en uitgevoerde query is geavanceerd spul. Raak niet in de war door meerdere lagen aanhalingstekens. In principe heb je EXECUTE
waarvoor een tekstargument nodig is dat de SQL-query bevat om uit te voeren. Deze tekst wordt op zijn beurt geleverd door een secundaire SQL-query die de queryreeks van de primaire query opbouwt.
Als dit teveel in één keer is of plpgsql
is vrij nieuw voor u, begin met dit gerelateerde antwoord
waar ik de basis uitleg over een veel eenvoudigere functie en links naar de handleiding voor de belangrijkste functies.
Als prestaties is essentieel om de Postgres-catalogus rechtstreeks te raadplegen (pg_catalog.pg_attributes
) in plaats van de gestandaardiseerde (maar trage) information_schema.columns
. Hier is een eenvoudig voorbeeld met pg_attributes
.