Объявите переменную табличного типа в PL / pgSQL

8

Мне интересно, есть ли способ объявить переменную таблицы типов в PL / pgSQL для хранения результатов запроса? Например, как я могу выразить что-то вроде:

q1 = select * from foo;
q2 = select * from bar;
for t1 in q1:
  for t2 in q2:
    -- do something with t1 and t2

Я посмотрел на конструкцию return next, но, похоже, способен обрабатывать только возвращаемые значения.

Дж.Р.Р.
источник
2
PL / SQL => Oracle, PgPL / SQL => PostgreSQL. С кем ты работаешь?
Мат
@Mat: это PL / pgSQL , кстати.
Эрвин Брандштеттер,

Ответы:

12

В PostgreSQL каждое имя таблицы автоматически служит в качестве имени типа для типа строки (также называемого составным типом ), а не типа таблицы, в Postgres нет «типов таблицы» или «табличных переменных» ( но есть типизированные таблицы ).
Таким образом, вы можете просто объявить переменную этого типа в PL/pgSQL.

CREATE FUNCTION foo()
 RETURNS void LANGUAGE plpgsql AS
$func$
DECLARE
  q1 foo;  -- "foo" ...
  q2 bar;  -- ... and "bar" are existing (visible) table names
BEGIN

FOR q1 IN 
   SELECT * from foo
LOOP
   FOR q2 IN 
      SELECT * from bar
   LOOP
       -- do something with q1 and q2
       -- since q1 and q2 are well known types, you can access columns
       -- with attribute notation. Like: q1.col1
   END LOOP;
END LOOP;

END
$func$

FORЦикл работает с встроенным курсором. В plpgsql также есть явные курсоры .

Вы также можете просто объявить переменные общего типа record. Может автоматически принимать любой тип строки при назначении. Но применяются особые правила. Обязательно перейдите по ссылке и прочитайте главу руководства!

Хотя часто SETOF <table name>возвращать SETOF recordфункцию удобно , возврат не так удобен. Система не знает, что функция возвращает таким образом, и вы должны добавлять список определений столбцов при каждом вызове. Что является болью. Подробности о табличных функциях в руководстве .

Тем не менее, часто есть более эффективные решения с простым SQL. Цикл является мерой последней инстанции, когда вы можете выполнять операции за одно сканирование, где вам потребуется несколько сканирований в чистом SQL.

Эрвин Брандштеттер
источник
2
Также обратите внимание, что если вы хотите вернуть тип таблицы, вы можете просто сказать что-то вродеCREATE FUNCTION footest() RETURNS SETOF foo LANGUAGE PLPGSQL AS $$...
Крис Траверс
Почему тогда у нас вообще есть функция «составных типов», если мы можем вместо этого создавать таблицы без ограничений, применяемых к составным типам (без ограничений и т. Д.)? Единственный осмысленный способ использования составных типов, которые я вижу, - это вернуть пару (или несколько) параметров из функции вместо создания целой таблицы для этого.
SaneDeveloper