Soluzione per il caso semplice
Come spiegato nelle risposte a cui si fa riferimento di seguito, puoi utilizzare tipi registrati (riga) e quindi dichiarare implicitamente il tipo restituito di una funzione polimorfica:
CREATE OR REPLACE FUNCTION public.get_table(_tbl_type anyelement)
RETURNS SETOF anyelement AS
$func$
BEGIN
RETURN QUERY EXECUTE format('TABLE %s', pg_typeof(_tbl_type));
END
$func$ LANGUAGE plpgsql;
Chiama:
SELECT * FROM public.get_table(NULL::public.users); -- note the syntax!
Restituisce la tabella completa (con tutte le colonne utente).
Aspetta! Come?
Spiegazione dettagliata in questa risposta correlata, capitolo"Vari tipi di tabelle complete" :
- Refactoring di una funzione PL/pgSQL per restituire l'output di varie query SELECT
TABLE foo
è solo l'abbreviazione di SELECT * FROM foo
:
- C'è una scorciatoia per SELECT * FROM?
2 passaggi per un tipo di reso completamente dinamico
Ma quello che stai cercando di fare è strettamente impossibile in un singolo Comando SQL.
Voglio passare schema_name
e table_name
come parametri per funzionare e ottenere l'elenco dei record, secondo column_visible
campo inpublic.fields
tabella.
Non esiste un modo diretto per restituire una selezione arbitraria di colonne (tipo restituito non noto al momento della chiamata) da una funzione - o qualsiasi Comando SQL. SQL richiede di conoscere numero, nomi e tipi di colonne risultanti al momento della chiamata. Altro nel 2° capitolo di questa risposta correlata:
- Come faccio a generare un CROSS JOIN con pivot in cui la definizione della tabella risultante è sconosciuta?
Esistono varie soluzioni alternative . Puoi racchiudere il risultato in uno dei tipi di documento standard (json
, jsonb
, hstore
, xml
).
Oppure generi la query con una chiamata di funzione ed esegui il risultato con la seguente:
CREATE OR REPLACE FUNCTION public.generate_get_table(_schema_name text, _table_name text)
RETURNS text AS
$func$
SELECT format('SELECT %s FROM %I.%I'
, string_agg(quote_ident(column_name), ', ')
, schema_name
, table_name)
FROM fields
WHERE column_visible
AND schema_name = _schema_name
AND table_name = _table_name
GROUP BY schema_name, table_name
ORDER BY schema_name, table_name;
$func$ LANGUAGE sql;
Chiama:
SELECT public.generate_get_table('public', 'users');
Questo crea una query del modulo:
SELECT usr_id, usr FROM public.users;
Eseguilo nel 2° passaggio. (Puoi aggiungere i numeri di colonna e ordinare le colonne.)
Oppure aggiungere \gexec
in psql per eseguire immediatamente il valore restituito. Vedi:
Come forzare la valutazione della sottoquery prima di entrare / spingere verso il server esterno
Assicurati di difenderti dall'iniezione di SQL:
- INSERT con nome tabella dinamica nella funzione trigger
- Definire i nomi di tabelle e colonne come argomenti in una funzione plpgsql?
varchar(100)
non ha molto senso per gli identificatori, che sono limitati a 63 caratteri in Postgres standard:
- Caratteri massimi nelle etichette (nomi di tabelle, colonne, ecc.)
Se capisci come l'identificatore di oggetto digita regclass
funziona, potresti sostituire lo schema e il nome della tabella con un unico regclass
colonna.