Серия расширенных баз данных (11): Хранимые процедуры PostgreSQL
Серия расширенных баз данных (11): Хранимые процедуры PostgreSQL

Могут возникнуть проблемы на работе. Дело сложнее.,Больше повторяющейся работы,нуждатьсяПакетная обработка данныхситуация,Используйте хранимую в это время процедура будет намного удобнее, Эффективность выполнения хранимой процедуры также будет намного выше.,Это может помочь нам сэкономить много кода и времени.

и,Волянуждатьсяизsqlнаписано какхранимая процедураИ установите это как запланированную задачу,Таким образом существовать в любое время,Вы можете выполнить его любое количество раз в соответствии с вашими настройками.,Даже если вы не на своем рабочем месте,Уменьшите свою рабочую нагрузку,Это сделает рыбалку более приятной для вас (нет).

Обзор PostgreSQL

В PostgreSQL, помимо стандартных операторов SQL, для удовлетворения потребностей программы создаются сложные процедуры и функции, которые мы называем хранимыми процедурами и пользовательскими функциями (User-Defined Function). Это помогает вам выполнять операции, которые обычно включают в себя несколько запросов и обращений в одну функцию в базе данных.

PL/pgSQL Его легко освоить, независимо от того, владеете ли вы основами программирования или нет, вы сможете освоить его быстро. ПЛ/pgSQL хранимая процедура, которая Oracle PL/SQL Очень похоже, да PostgreSQL по умолчанию поддерживает хранимую информацию. процедура, вот краткий анализ процедуры.

преимущество
  • Уменьшите приложение и базу Сетевая передача между данными. все SQL Заявления хранятся в существующем базовом режиме сервера данных середина, приложению нужно только отправить вызов функции и дополнительно получить результат, избегая отправки нескольких SQL заявление и дождитесь результата.
  • Улучшите производительность приложений. Потому что пользовательская функция и хранимая процедура предварительно компилируется и сохраняется в существующем базовом режиме сервер данных.
  • Многоразовость. Функции хранимой процедуры и функции могут использоваться несколькими приложениями одновременно.
  • Используется в качестве сценария, например, продукта liquibase середина, Очистка или восстановление данных будет очень полезна.
недостаток
  • В результате медленная разработка программного обеспечения. Потому что хранимая Процедуру нужно изучать отдельно, а у многих разработчиков нет этого навыка.
  • Нелегко осуществлять управление версиями и отладку кода.
  • Его нельзя переносить между разными системами управления базами данных, и существуют большие различия в синтаксисе.
  • Базовая структура хранимой процедуры
определить функцию
Язык кода:javascript
копировать
CREATE [ OR REPLACE ] FUNCTION
    name ( [ [ argmode ] [ argname ] argtype [ { DEFAULT | = } default_expr ] [, ...] ] )
    [ RETURNS rettype
      | RETURNS TABLE ( column_name column_type [, ...] ) ]
  { LANGUAGE lang_name
    | TRANSFORM { FOR TYPE type_name } [, ... ]
    | WINDOW
    | IMMUTABLE | STABLE | VOLATILE | [ NOT ] LEAKPROOF
    | CALLED ON NULL INPUT | RETURNS NULL ON NULL INPUT | STRICT
    | [ EXTERNAL ] SECURITY INVOKER | [ EXTERNAL ] SECURITY DEFINER
    | PARALLEL { UNSAFE | RESTRICTED | SAFE }
    | COST execution_cost
    | ROWS result_rows
    | SUPPORT support_function
    | SET configuration_parameter { TO value | = value | FROM CURRENT }
    | AS 'definition'
    | AS 'obj_file', 'link_symbol'
  } ...

определение получено из официального документа: http://postgres.cn/docs/12/sql-createfunction.html. Грамматика функции, конечно, не требует, чтобы все элементы были определены в реальности. Теперь существование объясняет часто используемые элементы.

  • CREATE ФУНКЦИЯ определяет новую функцию. СОЗДАВАТЬ OR REPLACE ФУНКЦИЯ создаст новую функцию или заменит существующую функцию.
  • имя: Указывает имя, которое будет создано
  • argmode: Режим параметра: IN, OUT, INOUTилиVARIADIC. Если опущено,По умолчанию — IN. Только за параметром OUT может следовать параметр VARIADIC. кроме,Параметры OUT и INOUT не могут использоваться с RETURNS вместе с символом TABLE.
  • argname: имя параметра
  • argtype: тип данных функционального параметра.
  • default_expr: выражение, которое будет использоваться в качестве значения по умолчанию, если параметр не указан.
  • rettype: возвращаемый тип данных,Если функция не возвращает значение,Тип возвращаемого значения может быть указан как void. (Подробнее позже)
  • имя_столбца: имя выходного столбца в синтаксисе RETURNS TABLE.
  • culumn_type:RETURNS тип данных выходного столбца в синтаксисе TABLE

Структура PL/pgSQL

Язык кода:javascript
копировать
[ <<label>> ]
[ DECLARE
    declarations ]
BEGIN
    statements
END [ label ];

PL/pgSQL — это язык с блочной структурой. Полный текст тела функции должен быть блоком. Синтаксис хранимой процедуры показан выше.

  • Каждое объявление и каждый оператор в блоке заканчивается точкой с запятой.
  • Все ключевые слова нечувствительны к регистру. Если идентификаторы не заключены в двойные кавычки, идентификаторы неявно преобразуются в нижний регистр, как и в обычных командах SQL.
  • Комментарии в коде PL/pgSQL такие же, как и в обычном SQL. Двойной дефис (–) начинает комментарий, доходящий до конца строки. /* запускает комментарий к блоку, который расширяется, чтобы соответствовать вхождению */. Комментарии к блокам могут быть вложенными.
синтаксис присваивания
объявить назначение переменной

Подробную информацию см. в официальной документации http://postgres.cn/docs/12/plpgsql-declarations.html.

Язык кода:javascript
копировать
name [ CONSTANT ] type [ COLLATE collation_name ] [ NOT NULL ] [ { DEFAULT | := | = } expression ];

Этот метод можно использовать при объявлении переменной в пользовательской функции и присвоении переменной значения. Примеры следующие:

Язык кода:javascript
копировать
-- 1
declare a integer default 32;
-- 2
declare a integer :=32;
-- 3
declare a integer;
a :=32;

Эти три метода могут объявить переменную a и присвоить ей значение 32. Если a не присвоено значение, даже если в третьем методе нет a:=32, об ошибке не будет сообщено, а переменная a инициализируется нулевым значением SQL.

  • константа: если добавлена ​​константа, это означает, что значение переменной не может быть изменено.
  • Сопоставить: укажите правило сортировки для переменной.
  • not null: если изменению присвоено нулевое значение, будет сообщено об ошибке.

Например, следующий метод сообщит об ошибке.

Язык кода:javascript
копировать
-- Ошибка 1
-- После добавления константы значение a не может быть изменено.
declare a constant integer default 32;
a :=1;
Язык кода:javascript
копировать
-- Ошибка 2
-- существования выбраны не при объявлении переменной null, вам следует присвоить значение при его объявлении, иначе ошибка все равно будет сообщена, даже если значение будет присвоено позже.
declare a integer not null;
a :=32;
динамическое назначение

Подробную информацию можно найти в официальной документации http://postgres.cn/docs/12/plpgsql-statements.html.

Метод 1: в предложение

Язык кода:javascript
копировать
SELECT select_expressions INTO [STRICT] target FROM ...;
INSERT ... RETURNING expressions INTO [STRICT] target;
UPDATE ... RETURNING expressions INTO [STRICT] target;
DELETE ... RETURNING expressions INTO [STRICT] target;

Например, следующим образом:

Язык кода:javascript
копировать
-- Это означает присвоение значения поля id в тестовой таблице
-- в select id from test — основная команда sql для запроса значения id из тестовой таблицы.
-- проходить into a Присвойте значение, полученное в результате запроса,
select id into a from test;

Способ 2: динамические команды

Язык кода:javascript
копировать
EXECUTE command-string [ INTO [STRICT] target ] [ USING expression [, ... ] ];

Например, следующим образом:

Язык кода:javascript
копировать
-- Как и выше, запросите значение id и присвойте его
execute 'select id from test' into a;

Тип возвращаемого значения

Официальная документация: http://postgres.cn/docs/12/xfunc-sql.html.

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

При наличии параметров OUT или INOUT предложение RETURNS можно опустить. Если оно присутствует, это предложение должно быть того же типа, что и результат, представленный выходными параметрами: RECORD, если имеется несколько выходных параметров, в противном случае тот же тип, что и один выходной параметр.

Возврат недействителен

Если функция не возвращает значение, вы можете указать тип возвращаемого значения как void. Если вы решите вернуть значение void, то тело функции не обязательно будет возвращаться в конце.

Язык кода:javascript
копировать
CREATE OR REPLACE FUNCTION "public"."func1"()
 RETURNS "pg_catalog"."void" AS $BODY$    -- returns void,существовать автоматически станет "pg_catalog"."void" при сохранении.
   
   BEGIN
   -- Создать оператор таблицы
   create table a(
   id int4,
   name varchar(50)
   );
   
END
$BODY$
 LANGUAGE plpgsql VOLATILE
 COST 100
Возвращает базовый тип

Возвращаемый результат — это любой базовый тип данных, например int4, float, text и т. д. Пример:

Язык кода:javascript
копировать
CREATE OR REPLACE FUNCTION "public"."func1"()
 RETURNS "pg_catalog"."text" AS $BODY$
   
   declare val text;
   BEGIN
   insert into a values (1, «Сяо Мин»)  returning name into val;
   
   return val;
END
$BODY$
 LANGUAGE plpgsql VOLATILE
 COST 100

Результат этой функции вернет значение val, как показано ниже:

И часть данных будет вставлена ​​в таблицу а, как показано ниже.

Ударьте по доске здесь! ! ! Здесь значение присваивается переменной через предложение In и возвращается первая строка результата или значение NULL (запрос возвращает ноль строк, если для сортировки не используется порядок по, первая строка неясна, и все результаты). после того, как первая строка будет отброшена.

Если добавлена ​​строгая опция, результатом запроса должна быть ровно одна строка, в противном случае будет сообщено об ошибке.

Например, теперь вставьте данные в таблицу a. Данные в таблице a следующие.

Затем запросите значение имени из таблицы и присвойте его значению val.

Язык кода:javascript
копировать
CREATE OR REPLACE FUNCTION "public"."func1"()
  RETURNS "pg_catalog"."text" AS $BODY$
 
 declare val text;
 
 BEGIN
 select name into val from a ;
 
 return val;
END
$BODY$
  LANGUAGE plpgsql VOLATILE
  COST 100

Полученные результаты показаны ниже. Возвращает строку данных, причем сорт первой строки не совпадает с первой строкой данных в таблице.

Если добавлена ​​строгая опция, будет сообщено об ошибке, если будет возвращено несколько фрагментов данных, как показано ниже.

Если возвращаемый результат представляет собой ровно одну строку данных, добавьте параметр strict для отображения окончательного результата.

Отобразите результаты в обычном режиме и вернитесь. Результат следующий:

Возврат нескольких фрагментов данных

На данный момент возвращаемые результаты либо пусты, либо являются записью. Что делать, если мне нужно несколько фрагментов данных?

  • возврат набора sometype
    • Модификатор SETOF указывает, что функция вернет коллекцию элементов, а не один элемент. когда ты вернулась набора При использовании sometype каждая строка, выводящаяся после выполнения последнего запроса, будет возвращена как элемент результирующего набора.
    • sometype может быть существующей таблицей или записью. Это также может быть определенный тип поля.

В приведенном выше примере, если вы хотите вернуть несколько записей, вы можете изменить его следующим образом.

Язык кода:javascript
копировать
CREATE OR REPLACE FUNCTION "public"."func1"()
  RETURNS SETOF "public"."a" AS $BODY$
 
 BEGIN

 return query select a.id,a.name from a limit 2;
 
 return;
END
$BODY$
  LANGUAGE plpgsql STABLE
  COST 100
  ROWS 1000

Полученный результат показан ниже.

Вы также можете использовать return next для запроса промежуточного возврата. Конкретный синтаксис:

Язык кода:javascript
копировать
RETURN NEXT expression;
RETURN QUERY query;
RETURN QUERY EXECUTE command-string [ USING expression [, ... ] ];

структура управления

postgresqlдоступен вструктура управления,иметьусловная структураи Структура цикла。

условная структура

Официальная документация: http://postgres.cn/docs/12/plpgsql-control-structures.html.

ЕСЛИ утверждение:

  • IF … THEN … END IF
  • IF … THEN … ELSE … END IF
  • IF … THEN … ELSIF … THEN … ELSE … END IF

Конкретный синтаксис можно посмотреть по официальной ссылке на документ. Теперь давайте рассмотрим небольшой пример.

Язык кода:javascript
копировать
CREATE OR REPLACE FUNCTION "public"."func1"("a" int4)
 RETURNS "pg_catalog"."text" AS $BODY$
   
   declare rel varchar;
   
   BEGIN

     IF a>=90 THEN
      rel:='Отлично';
     elsif a>=80 then
       rel := 'хороший';
     elsif a>=60 then
       rel := 'проходить';
     ELSE
      rel :='не удалось';
     END IF;

   return rel;
END
$BODY$
 LANGUAGE plpgsql STABLE
 COST 100

Заявление CASE:

  • CASE … WHEN … THEN … ELSE … END CASE
  • CASE WHEN … THEN … ELSE … END CASE

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

Язык кода:javascript
копировать
CREATE OR REPLACE FUNCTION "public"."func1"("a" int4)
  RETURNS "pg_catalog"."text" AS $BODY$
 
 declare rel varchar;
 
 BEGIN

  case when a>=90 THEN
     rel:='Отлично';
    when a>=80 then
     rel := 'хороший';
    when a>=60 then
     rel := 'проходить';
    ELSE
     rel :='не удалось';
  END case;

 return rel;
END
$BODY$
  LANGUAGE plpgsql STABLE
  COST 100
Структура цикла

Официальная документация: http://postgres.cn/docs/12/plpgsql-control-structures.html.

Структура цикла имеет операторы цикла, выхода, продолжения, while, for и foreach.

  • loop
Язык кода:javascript
копировать
[ <<label>> ]
LOOP
   statements
END LOOP [ label ];

цикл определяет безусловный цикл, который будет повторяться бесконечно, пока не будет завершен оператором выхода или возврата, поэтому

  • exit
Язык кода:javascript
копировать
EXIT [ label ] [ WHEN boolean-expression ];

Укажите, когда выходить из цикла, если логическое выражение истинно. Приведите пример с циклом.

Язык кода:javascript
копировать
 LOOP
  raise notice 'a is %',a;
  a :=a-1;

  IF a<=rel THEN
   EXIT; 
  END IF; 
 END LOOP;

-- Эквивалентно
 LOOP
  raise notice 'a is %',a;
  a :=a-1;

  EXIT when a<=rel;      -- Это эквивалентно всему суждению if перед
 END LOOP;

Выполните функцию и передайте параметр 5, после чего отображаемый результат будет следующим:

  • continue
Язык кода:javascript
копировать
CONTINUE [ label ] [ WHEN boolean-expression ];
  • while
Язык кода:javascript
копировать
[ <<label>> ]
WHILE boolean-expression LOOP
   statements
END LOOP [ label ];

Этот цикл будет выполняться, когда логическое выражение истинно. Пример:

Язык кода:javascript
копировать
CREATE OR REPLACE FUNCTION "public"."loops"("a" int4)
  RETURNS "pg_catalog"."void" AS $BODY$
 
 declare rel integer default 0;
 
 BEGIN
 
 WHILE a>0 LOOP
  raise info 'a= %',a;
  rel := rel+a;
  a:=a-1;
 END LOOP;
 
 raise info 'rel = %',rel;
 
END
$BODY$
  LANGUAGE plpgsql VOLATILE
  COST 100

Выполните входной параметр функции 5 и получите следующую информацию:

  • for

Цикл целочисленного диапазона.

Язык кода:javascript
копировать
[ <<label>> ]
FOR name IN [ REVERSE ] expression .. expression [ BY expression ] LOOP
    statements
END LOOP [ label ];

Цикл for создает целое число и возвращает его для итерации. В это время нижнее критическое значение меньше верхнего критического значения. Если указано обратное значение, верхнее критическое значение записывается первым, а нижнее критическое значение записывается последним. Размер шага по умолчанию равен 1. Если это прямая итерация. , значение каждой итерации увеличивается на 1. , если это обратная итерация, оно будет уменьшено на 1. Через by вы можете указать размер шага.

Например:

Язык кода:javascript
копировать
FOR i IN 1..10 LOOP
   -- Мой цикл существования примет значение 1,2,3,4,5,6,7,8,9,10 
END LOOP;

FOR i IN REVERSE 10..1 LOOP
   -- Мой цикл существования примет значение 10,9,8,7,6,5,4,3,2,1 
END LOOP;

FOR i IN REVERSE 10..1 BY 2 LOOP
   -- Мой цикл существования примет значение 10,8,6,4,2 
END LOOP;

Цикл результатов запроса

Язык кода:javascript
копировать
[ <<label>> ]
FOR target IN query LOOP
    statements
END LOOP [ label ];

Цель — это переменная записи, переменная строки или список скалярных переменных, разделенных запятыми. Цель постоянно назначается каждой строке запроса, а тело цикла будет выполняться один раз для каждой строки. Вот пример:

Язык кода:javascript
копировать
CREATE OR REPLACE FUNCTION "public"."loops"()
  RETURNS "pg_catalog"."void" AS $BODY$
 
 declare rel record;
 
 BEGIN
 
 FOR rel IN select id,name from a LOOP
  -- Функция quote_ident() заключается в добавлении к строке двойных кавычек.
  raise notice 'Информация о пользователе в таблице a: id: %,name: %',rel.id,quote_ident(rel.name);
 
 END LOOP;

END
$BODY$
  LANGUAGE plpgsql VOLATILE
  COST 100

Результаты показаны ниже:

Другой способ, которым оператор for-in-execute перебирает строки:

Язык кода:javascript
копировать
[ <<label>> ]
FOR target IN EXECUTE text_expression [ USING expression [, ... ] ] LOOP
    statements
END LOOP [ label ]

При использовании EXECUTE значения параметров можно вставлять в динамические команды через USING.

  • foreach

Цикл FOREACH во многом похож на цикл FOR, но вместо перебора строк, возвращаемых запросом SQL, он перебирает элементы значения массива.

Язык кода:javascript
копировать
[ <<label>> ]
FOREACH target [ SLICE number ] IN ARRAY expression LOOP
    statements
END LOOP [ label ];

Конкретные примеры приводить больше не будут, посмотрите примеры в официальной документации.

Язык кода:javascript
копировать
CREATE FUNCTION sum(int[]) RETURNS int8 AS $$
DECLARE
  s int8 := 0;
  x int;
BEGIN
  FOREACH x IN ARRAY $1
  LOOP
    s := s + x;
  END LOOP;
  RETURN s;
END;
$$ LANGUAGE plpgsql;

Подсказка

Официальная документация: http://postgres.cn/docs/12/plpgsql-errors-and-messages.html.

Используйте оператор повышения для сообщения о сообщениях и ошибках. Часть приведенного выше примера приведена.

Язык кода:javascript
копировать
RAISE [ level ] 'format' [, expression [, ... ]] [ USING option = expression [, ... ] ];
RAISE [ level ] condition_name [ USING option = expression [, ... ] ];
RAISE [ level ] SQLSTATE 'sqlstate' [ USING option = expression [, ... ] ];
RAISE [ level ] USING option = expression [, ... ];
RAISE ;

Опция level указывает серьезность ошибки. Допустимые уровни: ОТЛАДКА, ЖУРНАЛ, ИНФОРМАЦИЯ, УВЕДОМЛЕНИЕ, ПРЕДУПРЕЖДЕНИЕ и ИСКЛЮЧЕНИЕ. Уровень по умолчанию — ИСКЛЮЧЕНИЕ.

Язык кода:javascript
копировать
raise log «Это сообщение журнала»; – Выходной файл журнала существует  
raise inof «Это сообщение»; – Следующая информация выводится на консоль существования  
raise notice «Это оперативное сообщение»;  
raise notice warning «Это предупреждение»;  
raise exception 'Это сообщение об исключении';

Вызов хранимой процедуры

когдахранимая После того, как процедура скомпилирована, как нам следует выполнить или Вызов хранимой А как насчет процедур? Синтаксис следующий.

Язык кода:javascript
копировать
select function_name();
select * from function_name();
select * from function_name where условия фильтра;    -- Когда возвращаемый результат представляет собой набор результатов из нескольких данных
select * from function_name() as tablename(column name,column type[,...]) ;   --Динамический возвращаемый набор результатов

курсор

PL/pgSQL-выброс позволяет нам инкапсулировать запрос.,Затем обрабатывайте по одной записи в наборе результатов за раз. текст может разбить большой набор результатов на множество маленьких записей,Дополнительно избегайте переполнения памяти;,Мы можем определить функцию, которая возвращает ссылку на объект.,Вызывающая программа может затем обработать возвращенный набор результатов на основе этой ссылки.

Шаги по использованию риска примерно следующие:

  • объявить химическую переменную;
  • Открытый воздух;
  • Получить результаты от воздействия;
  • Определите, существуют ли еще результаты. Если он существует, перейдите к шагу 3, в противном случае перейдите к шагу 5;
  • Закрыть воздух.

Мы напрямуюпроходить Пример демонстрирует использованиекурсорпроцесс:

Язык кода:javascript
копировать
DO $$
DECLARE 
  rec_emp RECORD;
  cur_emp CURSOR(p_deptid INTEGER) FOR
    SELECT first_name, last_name, hire_date 
    FROM employees
    WHERE department_id = p_deptid;
BEGIN
  -- Открытый воздух
  OPEN cur_emp(60);

  LOOP
    -- Получайте записи в опасности
    FETCH cur_emp INTO rec_emp;
    -- Выйти из цикла, когда данные больше не найдены
    EXIT WHEN NOT FOUND;

    RAISE NOTICE '%,% hired at:%' , rec_emp.first_name, rec_emp.last_name, rec_emp.hire_date;
  END LOOP;

  -- Close the cursor
  CLOSE cur_emp;
END $$;

NOTICE:  Alexander,Hunold hired at:2006-01-03
NOTICE:  Bruce,Ernst hired at:2007-05-21
NOTICE:  David,Austin hired at:2005-06-25
NOTICE:  Valli,Pataballa hired at:2006-02-05
NOTICE:  Diana,Lorentz hired at:2007-02-07

Сначала объявите об опасности cur_emp и связывает оператор запроса через параметр p_deptid Получить сотрудников указанного отдела, а затем использовать; OPEN Открытый воздух, за которым следует существование, используемое в цикле; FETCH заявление Получайте записи в опасности,если неиметьнайти большеданныевыход из циклазаявление;переменная rec_emp Используется для хранения записей в последнем использованном помещении; CLOSE Заявление закрывает ситуацию и освобождает ресурсы.

курсорда PL/pgSQL Это мощная функция обработки данных. Дополнительные способы использования можно найти в официальной документации: https://www.postgresql.org/docs/current/plpgsql-cursors.html.

управление транзакциями

Внутри хранимой процедуры вы можете использовать COMMIT или ROLLBACK заявлениепредставлять на рассмотрениеили Откат транзакции。Например:

Язык кода:javascript
копировать
create table test(a int);

CREATE PROCEDURE transaction_test()
LANGUAGE plpgsql
AS $$
BEGIN
    FOR i IN 0..9 LOOP
        INSERT INTO test (a) VALUES (i);
        IF i % 2 = 0 THEN
            COMMIT;
        ELSE
            ROLLBACK;
        END IF;
    END LOOP;
END
$$;

CALL transaction_test();
select * from test;
a|
-|
0|
2|
4|
6|
8|

Случай

Выше приведен основной синтаксис хранимых процедур. Далее мы приведем несколько конкретных примеров для его закрепления.

Случай: Когда нет результатов запроса,Нет необходимости выбирать,Используйте выполнение.

Язык кода:javascript
копировать
CREATE OR REPLACE FUNCTION "public"."fun_etc"()
  RETURNS "pg_catalog"."void" AS $BODY$
 
 BEGIN
 perform current_date;

END
$BODY$
  LANGUAGE plpgsql VOLATILE
  COST 100

Случай 2: для запроса результатов Цикл объявить тип копии синтаксиса (копировать переменную строки)

Копировать тип строки,оператор синтаксиса:v_value table_name%ROWTYPE 。若да拷贝一个已иметьиз列данныетип,грамматика:v_value variable%TYPE,похожийdeclare b a.name%TYPE

Язык кода:javascript
копировать
CREATE OR REPLACE FUNCTION "public"."fun_etc"()
  RETURNS "pg_catalog"."text" AS $BODY$
 
 declare b a%rowtype;  
 
 BEGIN
 for b in select id,name from a loop
   raise info 'значение b=%',b;
   
  end loop;
 
return b.id||'---'||b.name;
 
END
$BODY$
  LANGUAGE plpgsql VOLATILE
  COST 100

Информационный результат:

return result: return вернет только последний результат выполнения.

Случай 3: Когда в операторах sql есть переменные,доступный||Сращивание,Наконец выполните.

Язык кода:javascript
копировать
CREATE OR REPLACE FUNCTION "public"."fun_etc"()
  RETURNS "pg_catalog"."void" AS $BODY$
 
 declare ifexists integer;
 declare sqltext text;  
 declare b record;
 
 BEGIN
 -- Определите, хранит ли таблица существование, значение существования=1 и значение существования=0, если это не так.
 sqltext:='
  select count(1)  from pg_class where relname=''a_'||to_char(CURRENT_DATE,'yyyy_mm_dd')||'''';
 execute sqltext into ifexists;
  
 -- Определите, существует ли существование в таблице, и создайте таблицу, если существование не существует.
 IF ifexists=0 then
 
  -- Создать новую таблицу
  sqltext:='
  
   create table "a_'||to_char(CURRENT_DATE,'yyyy_mm_dd')||'" 
   (
   create_time date,
   id int4,
   name varchar(50)
   );';
   
  execute sqltext;
 
 END IF;
 
 -- Запросите данные из таблицы a и вставьте их в эту таблицу.
 sqltext :='
 insert into a_'||to_char(CURRENT_DATE,'yyyy_mm_dd')||' 
 select CURRENT_DATE,id,name from a
 ';
 
 execute sqltext;

 -- Запрос показывает данные
 sqltext:= 'select create_time,id,name from a_'||to_char(CURRENT_DATE,'yyyy_mm_dd')||';';
 for b in execute sqltext loop
  raise info '%',b;
  
 end loop;
 
 return ;
 
END
$BODY$
  LANGUAGE plpgsql VOLATILE
  COST 100

Случай четвертый: сделать функцию более универсальной,Чтобы решить проблему динамического возврата наборов данных,Передайте имя таблицы в качестве параметра.

Язык кода:javascript
копировать
CREATE OR REPLACE FUNCTION "public"."fun_etc"("name" varchar)
  RETURNS SETOF "pg_catalog"."record" AS $BODY$
 
 declare b record;
 
 BEGIN
 
  for b in execute 'select * from '||name loop
 
   return next b;
 end loop;
 
 return ;
END
$BODY$
  LANGUAGE plpgsql VOLATILE
  COST 100
  ROWS 1000
Язык кода:javascript
копировать
select * from fun_etc('a') as a(id int,name varchar(50));

Результаты показывают:

Язык кода:javascript
копировать
select * from fun_etc('a_2022_12_21') as a(create_time date,id int,name varchar(50));

Результаты показывают:

Еще следует отметить, что здесь я изменяю функцию. Если параметры одинаковы, он модифицирует ее в исходной функции, поэтому не делайте этого, иначе это будет напрасно.

Справочная статья: https://blog.csdn.net/youzi85/article/details/128276130

boy illustration
Неразрушающее увеличение изображений одним щелчком мыши, чтобы сделать их более четкими артефактами искусственного интеллекта, включая руководства по установке и использованию.
boy illustration
Копикодер: этот инструмент отлично работает с Cursor, Bolt и V0! Предоставьте более качественные подсказки для разработки интерфейса (создание навигационного веб-сайта с использованием искусственного интеллекта).
boy illustration
Новый бесплатный RooCline превосходит Cline v3.1? ! Быстрее, умнее и лучше вилка Cline! (Независимое программирование AI, порог 0)
boy illustration
Разработав более 10 проектов с помощью Cursor, я собрал 10 примеров и 60 подсказок.
boy illustration
Я потратил 72 часа на изучение курсорных агентов, и вот неоспоримые факты, которыми я должен поделиться!
boy illustration
Идеальная интеграция Cursor и DeepSeek API
boy illustration
DeepSeek V3 снижает затраты на обучение больших моделей
boy illustration
Артефакт, увеличивающий количество очков: на основе улучшения характеристик препятствия малым целям Yolov8 (SEAM, MultiSEAM).
boy illustration
DeepSeek V3 раскручивался уже три дня. Сегодня я попробовал самопровозглашенную модель «ChatGPT».
boy illustration
Open Devin — инженер-программист искусственного интеллекта с открытым исходным кодом, который меньше программирует и больше создает.
boy illustration
Эксклюзивное оригинальное улучшение YOLOv8: собственная разработка SPPF | SPPF сочетается с воспринимаемой большой сверткой ядра UniRepLK, а свертка с большим ядром + без расширения улучшает восприимчивое поле
boy illustration
Популярное и подробное объяснение DeepSeek-V3: от его появления до преимуществ и сравнения с GPT-4o.
boy illustration
9 основных словесных инструкций по доработке академических работ с помощью ChatGPT, эффективных и практичных, которые стоит собрать
boy illustration
Вызовите deepseek в vscode для реализации программирования с помощью искусственного интеллекта.
boy illustration
Познакомьтесь с принципами сверточных нейронных сетей (CNN) в одной статье (суперподробно)
boy illustration
50,3 тыс. звезд! Immich: автономное решение для резервного копирования фотографий и видео, которое экономит деньги и избавляет от беспокойства.
boy illustration
Cloud Native|Практика: установка Dashbaord для K8s, графика неплохая
boy illustration
Краткий обзор статьи — использование синтетических данных при обучении больших моделей и оптимизации производительности
boy illustration
MiniPerplx: новая поисковая система искусственного интеллекта с открытым исходным кодом, спонсируемая xAI и Vercel.
boy illustration
Конструкция сервиса Synology Drive сочетает проникновение в интрасеть и синхронизацию папок заметок Obsidian в облаке.
boy illustration
Центр конфигурации————Накос
boy illustration
Начинаем с нуля при разработке в облаке Copilot: начать разработку с минимальным использованием кода стало проще
boy illustration
[Серия Docker] Docker создает мультиплатформенные образы: практика архитектуры Arm64
boy illustration
Обновление новых возможностей coze | Я использовал coze для создания апплета помощника по исправлению домашних заданий по математике
boy illustration
Советы по развертыванию Nginx: практическое создание статических веб-сайтов на облачных серверах
boy illustration
Feiniu fnos использует Docker для развертывания личного блокнота Notepad
boy illustration
Сверточная нейронная сеть VGG реализует классификацию изображений Cifar10 — практический опыт Pytorch
boy illustration
Начало работы с EdgeonePages — новым недорогим решением для хостинга веб-сайтов
boy illustration
[Зона легкого облачного игрового сервера] Управление игровыми архивами
boy illustration
Развертывание SpringCloud-проекта на базе Docker и Docker-Compose