sql >> Database >  >> RDS >> PostgreSQL

Query's dynamisch uitvoeren in PL/pgSQL

Systeemstatistieken

Bekijk voordat je je eigen rol gaat de systeemtabel pg_statistic of de weergave pg_stats :

Het kan al enkele van de statistieken bevatten die u gaat berekenen. Het wordt ingevuld door ANALYZE , dus u kunt dat voor nieuwe (of andere) tabellen uitvoeren voordat u het controleert.

-- ANALYZE tbl;  -- optionally, to init / refresh
SELECT * FROM pg_stats
WHERE tablename = 'tbl'
AND   schemaname = 'public';

Algemene dynamische plpgsql-functie

U wilt de minimumwaarde voor elke kolom in een bepaalde tabel . Dit is geen triviale taak, omdat een functie (zoals SQL in het algemeen) vraagt ​​om het retourtype te weten tijdens de aanmaaktijd - of in ieder geval tijdens het aanroepen met behulp van polymorfe gegevenstypen.

Deze functie doet alles automatisch en veilig. Werkt voor elke tabel, zolang de aggregatiefunctie min() is toegestaan ​​voor elke kolom. Maar je nodig om je weg te vinden in 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$;

Bel (belangrijk!):

SELECT * FROM f_min_of(NULL::tbl);  -- tbl being the table name

db<>fiddle hier
Oude sqlfiddle

U moet deze concepten begrijpen:

  • Dynamische SQL in plpgsql met EXECUTE
  • Polymorfe typen
  • Rijtypen en tabeltypen in Postgres
  • Hoe te verdedigen tegen SQL-injectie
  • Totale functies
  • Systeemcatalogi

Gerelateerd antwoord met gedetailleerde uitleg:

Speciale moeilijkheid met niet-overeenkomende typen

Ik maak gebruik van Postgres die een rijtype definieert voor elke bestaande tabel. Met behulp van het concept van polymorfe typen kan ik één . maken functie die voor elke tafel werkt.

Sommige statistische functies retourneren echter gerelateerde maar verschillende gegevenstypen in vergelijking met de onderliggende kolom. Bijvoorbeeld, min(varchar_column) retourneert text , die bit-compatibel is, maar niet precies hetzelfde gegevenstype. PL/pgSQL-functies hebben hier een zwakke plek en staan ​​exact op datatypes zoals aangegeven in de RETURNS clausule. Geen poging tot casten, zelfs geen impliciete casts, om nog maar te zwijgen van opdrachtcasts.

Dat zou verbeterd moeten worden. Getest met Postgres 9.3. Ik heb niet opnieuw getest met 9.4, maar ik ben er vrij zeker van dat er op dit gebied niets is veranderd.

Dat is waar deze constructie binnenkomt als oplossing :

SELECT (t::tbl).* FROM (SELECT ... FROM tbl) t;

Door de hele rij expliciet naar het rijtype van de onderliggende tabel te casten, dwingen we toewijzingscasts om originele gegevenstypen voor elke kolom te krijgen.

Dit kan mislukken voor een bepaalde aggregatiefunctie. sum() retourneert numeric voor een sum(bigint_column) om tegemoet te komen aan een som die het basisgegevenstype overschrijdt. Terug casten naar bigint kan mislukken ...



  1. PHPMailer verzendt dubbele e-mails

  2. Beveiliging tegen SQL-injectie - enkele aanhalingstekens

  3. SQL Server:CREATE ASSEMBLY voor assembly 'Test' is mislukt omdat assembly 'Test' niet goed is opgemaakt of geen pure .NET-assembly is.

  4. Kolomsortering converteren naar standaard tabel/database