PostgreSQL
 sql >> Baza danych >  >> RDS >> PostgreSQL

Dynamiczne wykonywanie zapytań w PL/pgSQL

Statystyki systemu

Zanim wyrzucisz własną, spójrz na tabelę systemową pg_statistic lub widok pg_stats :

Może już zawierać niektóre statystyki, które zamierzasz obliczyć. Jest wypełniany przez ANALYZE , więc możesz uruchomić to dla nowych (lub dowolnych) tabel przed sprawdzeniem.

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

Ogólna dynamiczna funkcja plpgsql

Chcesz zwrócić wartość minimalną dla każdej kolumny w danej tabeli . Nie jest to trywialne zadanie, ponieważ funkcja (jak ogólnie SQL) wymaga znajomości typu zwracanego w czasie tworzenia - lub przynajmniej w czasie wywołania za pomocą polimorficznych typów danych.

Ta funkcja robi wszystko automatycznie i bezpiecznie. Działa dla każdego tabeli, o ile funkcja agregująca min() jest dozwolony dla każdej kolumny. Ale potrzebujesz poznać 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$;

Zadzwoń (ważne!):

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

db<>fiddle tutaj
Stary sqlfiddle

Musisz zrozumieć te pojęcia:

  • Dynamiczny SQL w plpgsql z EXECUTE
  • Typy polimorficzne
  • Typy wierszy i typy tabel w Postgresie
  • Jak bronić się przed wstrzyknięciem SQL
  • Funkcje agregujące
  • Katalogi systemowe

Powiązana odpowiedź ze szczegółowym wyjaśnieniem:

Specjalny poziom trudności z niezgodnością typów

Korzystam z możliwości Postgresa definiującego typ wiersza dla każdej istniejącej tabeli. Korzystając z koncepcji typów polimorficznych, jestem w stanie stworzyć jeden funkcja, która działa dla każdej tabeli.

Jednak niektóre funkcje agregujące zwracają powiązane, ale różne typy danych w porównaniu z kolumną bazową. Na przykład min(varchar_column) zwraca text , który jest zgodny z bitami, ale nie dokładnie ten sam typ danych. Funkcje PL/pgSQL mają tutaj słaby punkt i nalegają na typy danych dokładnie zgodnie z deklaracją w RETURNS klauzula. Żadnych prób rzutowania, nawet ukrytych rzutów, nie mówiąc już o rzutach przypisania.

To powinno zostać poprawione. Testowane z Postgresem 9.3. Nie testowałem ponownie z wersją 9.4, ale jestem prawie pewien, że w tym obszarze nic się nie zmieniło.

Właśnie tam pojawia się ta konstrukcja jako obejście :

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

Rzutując cały wiersz na typ wiersza tabeli bazowej, wymuszamy rzutowanie przypisania, aby uzyskać oryginalne typy danych dla każdej kolumny.

Może to zakończyć się niepowodzeniem w przypadku niektórych funkcji agregujących. sum() zwraca numeric dla sum(bigint_column) aby pomieścić sumę przepełniającą podstawowy typ danych. Przesyłanie z powrotem do bigint może się nie udać ...



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Używanie tabeli tymczasowej do zastąpienia klauzuli WHERE IN

  2. Odmowa uprawnień podczas próby importowania pliku CSV z PGAdmin

  3. Zamiast LIKE i ~, dlaczego tylko SIMILAR TO działa podczas dopasowywania wyrażeń regularnych z alternatywami

  4. Funkcje refaktoryzacji, aby można było ich używać w ramach CTE

  5. BŁĄD :Indeks kolumny jest poza zakresem:1, liczba kolumn:0