PostgreSQL
 sql >> база данни >  >> RDS >> PostgreSQL

Динамично изпълнение на заявки в PL/pgSQL

Системна статистика

Преди да направите своя собствена, погледнете системната таблица pg_statistic или изгледа pg_stats :

Може вече да има някои от статистическите данни, които предстои да изчислите. Попълва се от ANALYZE , така че можете да го изпълните за нови (или всякакви) таблици, преди да проверите.

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

Обща динамична plpgsql функция

Искате да върнете минималната стойност за всяка колона в дадена таблица . Това не е тривиална задача, тъй като една функция (като SQL като цяло) изисква да знае типа на връщането по време на създаване - или поне по време на извикване с помощта на полиморфни типове данни.

Тази функция прави всичко автоматично и безопасно. Работи за всеки таблица, стига агрегатната функция min() е разрешено за всяка колона. Но вие имате нужда за да се ориентирате в 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$;

Обадете се (важно!):

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

db<>fiddle тук
Стар sqlfiddle

Трябва да разберете тези понятия:

  • Динамичен SQL в plpgsql с EXECUTE
  • Полиморфни типове
  • Типове редове и типове таблици в Postgres
  • Как да се защитим от SQL инжектиране
  • Агрегирани функции
  • Системни каталози

Свързан отговор с подробно обяснение:

Специална трудност с несъответствие на типа

Възползвам се от Postgres, дефинирайки тип ред за всяка съществуваща таблица. Използвайки концепцията за полиморфни типове, мога да създам един функция, която работи за всяка таблица.

Някои агрегатни функции обаче връщат свързани, но различни типове данни в сравнение с основната колона. Например min(varchar_column) връща text , което е битово съвместимо, но не точно същия тип данни. PL/pgSQL функциите имат слабо място тук и настояват за типове данни точно както е декларирано в RETURNS клауза. Никакви опити за кастиране, дори косвени кастинги, да не говорим за кастинги на присвояване.

Това трябва да се подобри. Тествано с Postgres 9.3. Не съм тествал отново с 9.4, но съм почти сигурен, че нищо не се е променило в тази област.

Това е мястото, където тази конструкция идва като заобиколно решение :

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

Чрез изрично прехвърляне на целия ред към типа ред на основната таблица ние принуждаваме преобразувания на присвояване да получат оригинални типове данни за всяка колона.

Това може да се провали за някаква агрегатна функция. sum() връща numeric за sum(bigint_column) за приспособяване за сума, превишаваща основния тип данни. Връщане към bigint може да се провали...



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. JSONB sqlalchemy агрегатна функция

  2. Как да премахнете дубликати, така че в таблица да съществуват само двойки?

  3. Функцията XPath sum или fn:sum внедрена ли е в PostgreSQL XPath?

  4. PostgreSQL:дублираната стойност на ключ нарушава уникалното ограничение на командата UPDATE

  5. SQL:Групирайте подобни стойности на колона B, но подредете по колона A