Systemstatistik
Før du ruller din egen, så tag et kig på systemtabellen pg_statistic
eller visningen pg_stats
:
Den har måske allerede nogle af de statistikker, du er ved at beregne. Den er udfyldt af ANALYZE
, så du kan køre det for nye (eller alle) tabeller, før du tjekker.
-- ANALYZE tbl; -- optionally, to init / refresh
SELECT * FROM pg_stats
WHERE tablename = 'tbl'
AND schemaname = 'public';
Generisk dynamisk plpgsql-funktion
Du vil returnere minimumsværdien for hver kolonne i en given tabel . Dette er ikke en triviel opgave, fordi en funktion (som SQL generelt) kræver at kende returtypen på oprettelsestidspunktet - eller i det mindste på opkaldstidspunktet ved hjælp af polymorfe datatyper.
Denne funktion gør alt automatisk og sikkert. Virker for alle tabel, så længe den samlede funktion min()
er tilladt for hver kolonne. Men du bruger at kende din vej rundt i PL/pgSQL.
CREATE OR REPLACE FUNCTION f_min_of(_tbl anyelement)
RETURNS SETOF anyelement
LANGUAGE plpgsql AS
$func$
BEGIN
RETURN QUERY EXECUTE (
SELECT format('SELECT (t::%2$s).* FROM (SELECT min(%1$s) FROM %2$s) t'
, string_agg(quote_ident(attname), '), min(' ORDER BY attnum)
, pg_typeof(_tbl)::text)
FROM pg_attribute
WHERE attrelid = pg_typeof(_tbl)::text::regclass
AND NOT attisdropped -- no dropped (dead) columns
AND attnum > 0 -- no system columns
);
END
$func$;
Ring (vigtigt!):
SELECT * FROM f_min_of(NULL::tbl); -- tbl being the table name
db<>fiddle her
Gamle sqlfiddle
Du skal forstå disse begreber:
- Dynamisk SQL i plpgsql med
EXECUTE
- Polymorfe typer
- Rækketyper og tabeltyper i Postgres
- Sådan forsvarer du dig mod SQL-injektion
- Aggregerede funktioner
- Systemkataloger
Relateret svar med detaljeret forklaring:
- Tabelnavn som en PostgreSQL funktionsparameter
- Refaktorer en PL/pgSQL-funktion for at returnere output fra forskellige SELECT-forespørgsler
- Postgres datatype cast
- Sådan indstilles værdien af det sammensatte variabelfelt ved hjælp af dynamisk SQL
- Sådan kontrollerer du, om en tabel findes i et givet skema
- Vælg kolonner med bestemte kolonnenavne i PostgreSQL
- Generer serier af datoer - brug datotype som input
Særlig vanskelighed med type uoverensstemmelse
Jeg udnytter, at Postgres definerer en rækketype for hver eksisterende tabel. Ved at bruge begrebet polymorfe typer er jeg i stand til at skabe en funktion, der virker for enhver tabel.
Nogle aggregerede funktioner returnerer dog relaterede men forskellige datatyper sammenlignet med den underliggende kolonne. For eksempel min(varchar_column)
returnerer text
, som er bitkompatibel, men ikke præcis samme datatype. PL/pgSQL-funktioner har et svagt punkt her og insisterer på datatyper præcis som angivet i RETURNS
klausul. Intet forsøg på at caste, ikke engang implicitte casts, for ikke at tale om opgavebesætninger.
Det bør forbedres. Testet med Postgres 9.3. Gentestede ikke med 9.4, men jeg er ret sikker på, at intet har ændret sig på dette område.
Det er her, denne konstruktion kommer ind som løsning :
SELECT (t::tbl).* FROM (SELECT ... FROM tbl) t;
Ved eksplicit at caste hele rækken til rækketypen i den underliggende tabel tvinger vi tildelingscasts til at få originale datatyper for hver kolonne.
Dette kan mislykkes for nogle samlede funktioner. sum()
returnerer numeric
for en sum(bigint_column)
for at rumme en sum, der flyder over basisdatatypen. Caster tilbage til bigint
kan mislykkes ...