Statistiche di sistema
Prima di fare il tuo, dai un'occhiata alla tabella di sistema pg_statistic
o la vista pg_stats
:
Potrebbe già avere alcune delle statistiche che stai per calcolare. È popolato da ANALYZE
, quindi potresti eseguirlo per nuove (o qualsiasi) tabelle prima di controllare.
-- ANALYZE tbl; -- optionally, to init / refresh
SELECT * FROM pg_stats
WHERE tablename = 'tbl'
AND schemaname = 'public';
Funzione plpgsql dinamica generica
Vuoi restituire il valore minimo per ogni colonna in una determinata tabella . Questo non è un compito banale, perché una funzione (come SQL in generale) richiede di conoscere il tipo restituito al momento della creazione, o almeno al momento della chiamata con l'aiuto di tipi di dati polimorfici.
Questa funzione fa tutto in modo automatico e sicuro. Funziona per qualsiasi tabella, purché la funzione di aggregazione min()
è consentito per ogni colonna. Ma tu hai bisogno per conoscere 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$;
Chiama (importante!):
SELECT * FROM f_min_of(NULL::tbl); -- tbl being the table name
db<>violino qui
Vecchio sqlfiddle
Devi comprendere questi concetti:
- SQL dinamico in plpgsql con
EXECUTE
- Tipi polimorfici
- Tipi di riga e tipi di tabella in Postgres
- Come difendersi da SQL injection
- Funzioni aggregate
- Cataloghi di sistema
Risposta correlata con spiegazione dettagliata:
- Nome tabella come Parametro della funzione PostgreSQL
- Refactoring di una funzione PL/pgSQL per restituire l'output di varie query SELECT
- Cast del tipo di dati Postgres
- Come impostare il valore del campo della variabile composita utilizzando SQL dinamico
- Come verificare se una tabella esiste in un determinato schema
- Seleziona colonne con nomi di colonne particolari in PostgreSQL
- Genera serie di date, utilizzando il tipo di data come input
Difficoltà speciale con tipo non corrispondente
Sto sfruttando Postgres per definire un tipo di riga per ogni tabella esistente. Utilizzando il concetto di tipi polimorfici sono in grado di crearne uno funzione che funziona per qualsiasi tabella.
Tuttavia, alcune funzioni di aggregazione restituiscono tipi di dati correlati ma diversi rispetto alla colonna sottostante. Ad esempio, min(varchar_column)
restituisce text
, che è compatibile con i bit, ma non esattamente lo stesso tipo di dati. Le funzioni PL/pgSQL hanno qui un punto debole e insistono sui tipi di dati esattamente come dichiarato nel RETURNS
clausola. Nessun tentativo di cast, nemmeno impliciti, per non parlare di cast di assegnazione.
Dovrebbe essere migliorato. Testato con Postgres 9.3. Non ho ripetuto il test con 9.4, ma sono abbastanza sicuro che non è cambiato nulla in quest'area.
È qui che entra in gioco questo costrutto come soluzione alternativa :
SELECT (t::tbl).* FROM (SELECT ... FROM tbl) t;
Trasmettendo in modo esplicito l'intera riga al tipo di riga della tabella sottostante, forziamo i cast di assegnazione per ottenere i tipi di dati originali per ogni colonna.
Questo potrebbe non riuscire per alcune funzioni aggregate. sum()
restituisce numeric
per un sum(bigint_column)
per accogliere una somma eccedente il tipo di dati di base. Ritorno a bigint
potrebbe non riuscire...