进阶数据库系列(十一):PostgreSQL 存储过程

这篇具有很好参考价值的文章主要介绍了进阶数据库系列(十一):PostgreSQL 存储过程。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

前面介绍了 PostgreSQL 数据类型和运算符、常用函数、锁操作、执行计划、视图与触发器相关的知识点,今天我将详细的为大家介绍 PostgreSQL 存储过程相关知识,希望大家能够从中收获多多!如有帮助,请点在看、转发支持一波!!!

工作中可能会存在业务比较复杂,重复性工作比较多,需要批量处理数据的情况,此时使用存储过程会方便很多,存储过程的执行效率也会快很多,能帮助我们节省很多代码和时间。

并且,将需要的sql写成存储过程并设置成定时任务,那样在任意时刻,需要执行任意次数都可以根据你的设定执行,哪怕你不在工位上,减少你的工作量,能让你更愉快的摸鱼(不是)。

PostgreSQL 概述

在 PostgreSQL 中,除了标准 SQL 语句之外,通过创建复杂的过程和函数来满足程序需要,我们称为存储过程和自定义函数(User-Defined Function)。它有助于您执行通常在数据库中的单个函数中进行多次查询和往返操作的操作。

PL/pgSQL 简单易学,无论是否具有编程基础都能够很快学会。PL/pgSQL 存储过程,它和 Oracle PL/SQL 非常类似,是 PostgreSQL默认支持的存储过程,下面针对优缺点给大家做了简要分析。

优点
  • 减少应用和数据库之间的网络传输。所有的 SQL 语句都存储在数据库服务器中,应用程序只需要发送函数调用并获取除了结果,避免了发送多个 SQL 语句并等待结果。

  • 提高应用的性能。因为自定义函数和存储过程进行了预编译并存储在数据库服务器中。

  • 可重用性。存储过程和函数的功能可以被多个应用同时使用。

  • 作为脚本使用,如产品的 liquibase 中, 清理或修复数据将非常好用。

缺点
  • 导致软件开发缓慢。因为存储过程需要单独学习,而且很多开发人员并不具备这种技能。

  • 不易进行版本管理和代码调试。

  • 不同数据库管理系统之间无法移植,语法存在较大的差异。

  • 更多关于大数据 PostgreSQL 系列的学习文章,请参阅:PostgreSQL 数据库,本系列持续更新中。

存储过程基本结构

定义一个函数
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'
  } ...

由官方文档得到的定义一个函数的语法,当然现实中不需要所有的要素都要定义到。现在就常用的要素做出解释。

  • CREATE FUNCTION定义一个新函数。CREATE OR REPLACE FUNCTION将创建一个新函数或者替换一个现有的函数

  • name:表示要创建的函数名

  • argmode:一个参数的模式:IN、OUT、INOUT或者VARIADIC。如果省略,默认为IN。只有OUT参数能跟在一个VARIADIC参数后面。还有,OUT和INOUT参数不能和RETURNS TABLE符号一起使用。

  • argname:一个参数的名称

  • argtype:该函数参数的数据类型

  • default_expr:如果参数没有被指定值时要用作默认值的表达式

  • rettype:返回的数据类型,如果该函数不会返回一个值,可以指定返回类型为void。(后面详细讲)

  • column_name:RETURNS TABLE语法中一个输出列的名称

  • culumn_type:RETURNS TABLE语法中的输出列的数据类型

注意:定义函数的时候,参数可以是空,但是哪怕不修改函数体只修改参数,它会得到一个新的函数。更多关于大数据 PostgreSQL 系列的学习文章,请参阅:PostgreSQL 数据库,本系列持续更新中。

PL/pgSQL 的结构
[ <<label>> ]
[ DECLARE
    declarations ]
BEGIN
    statements
END [ label ];

PL/pgSQL是一种块结构的语言。一个函数体的完整文本必须是一个块。存储过程的语法如上所示。

  • 在一个块中的每一个声明和每一个语句都由一个分号终止。

  • 所有的关键词都是大小写无关的。除非被双引号引用,标识符会被隐式地转换为小写形式,就像它们在普通 SQL 命令中。

  • PL/pgSQL代码中的注释和普通 SQL 中的一样。一个双连字符(–)开始一段注释,它延伸到该行的末尾。一个/* 开始一段块注释,它会延伸到匹配*/出现的位置。块注释可以嵌套。

赋值语法
声明变量赋值

具体可看官方文档

name [ CONSTANT ] type [ COLLATE collation_name ] [ NOT NULL ] [ { DEFAULT | := | = } expression ];

在自定义函数中声明一个变量,并给这个变量赋值的时候可以用这个方法。示例如下:

-- 1
declare a integer default 32;
-- 2
declare a integer :=32;
-- 3
declare a integer;
a :=32;

这三种方法都能将声明一个变量a,并且将32赋值给a。若不给a赋值,就是方法三中没有a:=32;也不会报错,就是变量a初始化为sql空值。

  • constant:若是增加constant,则表示该变量的值无法修改

  • collate:给该变量指定一个排序规则

  • not null:如果给改变量赋值为空值会报错

例如,以下方式就会报错。

-- 报错1
-- 加了constant,已经无法修改a的值了。
declare a constant integer default 32;
a :=1;

pg 存储过程,PostgreSQL 随笔,数据库,postgresql

-- 报错2
-- 在声明变量的时候选择了not null,就应该在声明时赋值,否则哪怕后面赋值还是会报错
declare a integer not null;
a :=32;

pg 存储过程,PostgreSQL 随笔,数据库,postgresql

动态赋值

具体可查看官方文档

方式一:into子句

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;

举个例子,如下:

-- 这就表示把test表中的id字段的值赋值给a
-- 其中 select id from test就是基础sql命令从test表中查询id的值
-- 通过 into a 将查询得到的值赋值给a
select id into a from test;

方式二:动态命令

EXECUTE command-string [ INTO [STRICT] target ] [ USING expression [, ... ] ];

举个例子,如下:

-- 和上面一样,把id的值查询出来赋值给a
execute 'select id from test' into a;

更多关于大数据 PostgreSQL 系列的学习文章,请参阅:PostgreSQL 数据库,本系列持续更新中。

返回值类型

官方文档:

pg 存储过程,PostgreSQL 随笔,数据库,postgresql

returns返回类型可以是一种基本类型、组合类型或者域类型,也可以引用一个表列的类型。

当有OUT或者INOUT参数时,可以省略RETURNS子句。如果存在,该子句必须和输出参数所表示的结果类型一致:如果有多个输出参数,则为RECORD,否则与单个输出参数的类型相同。

返回void

如果该函数不会返回一个值,可以指定返回类型为void。如果选择返回returns void,那函数体最后就不用return了。

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

pg 存储过程,PostgreSQL 随笔,数据库,postgresql

pg 存储过程,PostgreSQL 随笔,数据库,postgresql

返回基本类型

返回的结果是类似int4,float,text等这些基本数据类型都可以。示例:

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

pg 存储过程,PostgreSQL 随笔,数据库,postgresql

这个函数的结果会返回val的值,如下图:
 

pg 存储过程,PostgreSQL 随笔,数据库,postgresql

并且在表a中会插入一条数据,如下图。
 

pg 存储过程,PostgreSQL 随笔,数据库,postgresql

这里敲黑板!!! 这里通过into子句赋值给变量,返回的是结果的第一行或者null(查询返回零行),除非使用order by进行排序,否则第一行是不明确的,第一行之后所有的结果都会被丢弃。

如果加了strict选项,那么查询结果必须是恰好一行,否则就会报错。

举个例子,现在在a表中插入数据,表a数据如下。
 

pg 存储过程,PostgreSQL 随笔,数据库,postgresql

然后从表中查询出name值赋值val。

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

得到的结果如下显示。返回一行数据,并且这个第一行的排序并不是表的第一行数据。
 

pg 存储过程,PostgreSQL 随笔,数据库,postgresql

若是添加strict选项,结果返回的是多条数据就会报错,如下显示。

pg 存储过程,PostgreSQL 随笔,数据库,postgresql

pg 存储过程,PostgreSQL 随笔,数据库,postgresql

如果返回的结果刚好是一行数据的,则添加strict选项就可以显示最终结果。

pg 存储过程,PostgreSQL 随笔,数据库,postgresql

正常显示结果并且返回。结果如下:

pg 存储过程,PostgreSQL 随笔,数据库,postgresql

返回多条数据

到目前为止,现在返回的结果要不是返回空要不就是返回一个记录,若是想要多条数据该怎么处理呢?

  • 返回setof sometype

    • SETOF修饰符表示该函数将返回一个项的集合而不是一个单一项。当被返回setof sometype时,函数最后一个查询执行完后输出的每一行都会被作为结果集的一个元素返回。

    • sometype可以是某一张已经存在的表,也可以是record。也可以是某个字段类型。

上面那个例子,若是想要返回多条记录,就可以修改如下。

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

得到的结果如下图。
 

pg 存储过程,PostgreSQL 随笔,数据库,postgresql

期中return query还可以使用return next。具体语法是:

RETURN NEXT expression;
RETURN QUERY query;
RETURN QUERY EXECUTE command-string [ USING expression [, ... ] ];

详细情况可以看查看官方文档。更多关于大数据 PostgreSQL 系列的学习文章,请参阅:PostgreSQL 数据库,本系列持续更新中。

控制结构

postgresql中可以使用的控制结构,有条件结构和循环结构。

条件结构

官方文档:

IF语句:

  • IF … THEN … END IF

  • IF … THEN … ELSE … END IF

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

具体语法官方文档链接中可查看,现在举个小例子看一个

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

pg 存储过程,PostgreSQL 随笔,数据库,postgresql

pg 存储过程,PostgreSQL 随笔,数据库,postgresql

CASE语句:

  • CASE … WHEN … THEN … ELSE … END CASE

  • CASE WHEN … THEN … ELSE … END CASE

同理上面的函数可以改成case when

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
循环结构

官方文档:

循环结构有loop,exit,continue,while,for和foreach语句

  • loop

[ <<label>> ]
LOOP
   statements
END LOOP [ label ];

loop定义的是一个无条件循环,会无限重复直到被exit或return语句终止,所以

  • exit

EXIT [ label ] [ WHEN boolean-expression ];

指定when,当boolean-expression为真时会退出循环。配合loop给个例子。

 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;

pg 存储过程,PostgreSQL 随笔,数据库,postgresql

执行函数,传入参数为5,则显示的结果如下:

pg 存储过程,PostgreSQL 随笔,数据库,postgresql

  • continue

CONTINUE [ label ] [ WHEN boolean-expression ];
  • while

[ <<label>> ]
WHILE boolean-expression LOOP
   statements
END LOOP [ label ];

当boolean-expression为真的时候,这个循环会执行。举例:

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

pg 存储过程,PostgreSQL 随笔,数据库,postgresql

执行函数输入参数5,得到信息如下:

pg 存储过程,PostgreSQL 随笔,数据库,postgresql

  • for

整数范围循环。

[ <<label>> ]
FOR name IN [ REVERSE ] expression .. expression [ BY expression ] LOOP
    statements
END LOOP [ label ];

for循环会创建一个整数返回进行迭代。此时下界临界值小于上界临界值,若是制定reverse,则上界临界值写在前,下界临界值写在后,默认步长为1,若是正向迭代,每次迭代数值都是加1,若是反向迭代都是减1。通过by,可以指定步长。

例如:

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;

查询结果循环

[ <<label>> ]
FOR target IN query LOOP
    statements
END LOOP [ label ];

target是一个记录变量、行变量或者逗号分隔的标量变量列表。target被连续不断被赋予来自query的每一行,并且循环体将为每一行执行一次。下面是一个例子:

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

结果显示如下:
 

pg 存储过程,PostgreSQL 随笔,数据库,postgresql

for-in-execute语句在行上迭代的另一种方式:

[ <<label>> ]
FOR target IN EXECUTE text_expression [ USING expression [, ... ] ] LOOP
    statements
END LOOP [ label ]

这个例子类似前面的形式,只不过源查询被指定为一个字符串表达式,在每次进入FOR循环时都会计算它并且重新规划。更多关于大数据 PostgreSQL 系列的学习文章,请参阅:PostgreSQL 数据库,本系列持续更新中。

在使用EXECUTE时,可以通过USING将参数值插入到动态命令中。

  • foreach

FOREACH循环很像一个FOR循环,但不是通过一个 SQL 查询返回的行进行迭代,它通过一个数组值的元素来迭代。

[ <<label>> ]
FOREACH target [ SLICE number ] IN ARRAY expression LOOP
    statements
END LOOP [ label ];

具体例子不再给出,看看官方文档中的例子。

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;

提示信息

官方文档:

使用raise语句报告消息以及抛出错误,上面给的示例中已经有部分给出,语法是。

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选项指定了错误的严重性。允许的级别有DEBUG、LOG、INFO、NOTICE, WARNING以及EXCEPTION,默认级别是EXCEPTION。

raise log ‘这是日志消息’; – 输出在日志文件中  
raise inof ‘这是一个信息’; – 以下信息打印在控制台  
raise notice ‘这个是提示消息’;  
raise notice warning ‘这是个警告’;  
raise exception ‘这个异常消息’;

调用存储过程

当存储过程编译出来后,我们该如何执行或者调用存储过程呢?语法如下。

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 步;

  • 关闭游标。

我们直接通过一个示例演示使用游标的过程:

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 中的一个强大的数据处理功能,更多的使用方法可以参考官方文档。

事务管理

在存储过程内部,可以使用 COMMIT 或者 ROLLBACK 语句提交或者回滚事务。例如:

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|

只有偶数才会被最终提交。更多关于大数据 PostgreSQL 系列的学习文章,请参阅:PostgreSQL 数据库,本系列持续更新中。

案例

以上就是存储过程的基本语法,接下来再给几个具体实例巩固一下。

案例一:无查询结果时,不用select,用perform。

CREATE OR REPLACE FUNCTION "public"."fun_etc"()
  RETURNS "pg_catalog"."void" AS $BODY$
 
 BEGIN
 perform current_date;

END
$BODY$
  LANGUAGE plpgsql VOLATILE
  COST 100

pg 存储过程,PostgreSQL 随笔,数据库,postgresql

案例二:for查询结果循环,声明语法拷贝类型(拷贝一个行变量)

拷贝行类型,语法声明:v_value table_name%ROWTYPE 。若是拷贝一个已有的列数据类型,语法:v_value variable%TYPE,类似declare b a.name%TYPE

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

pg 存储过程,PostgreSQL 随笔,数据库,postgresql

信息结果:

pg 存储过程,PostgreSQL 随笔,数据库,postgresql

return返回结果:return返回只会返回执行的最后一个结果。

pg 存储过程,PostgreSQL 随笔,数据库,postgresql

案例三:当sql中的语句有变量的时候,可以用||拼接,最后execute执行。

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

pg 存储过程,PostgreSQL 随笔,数据库,postgresql

pg 存储过程,PostgreSQL 随笔,数据库,postgresql

pg 存储过程,PostgreSQL 随笔,数据库,postgresql

案例四:为了使函数更加通用,以解决动态返回数据集的问题,将表名作为参数传进去。

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
select * from fun_etc('a') as a(id int,name varchar(50));

结果显示:

pg 存储过程,PostgreSQL 随笔,数据库,postgresql

select * from fun_etc('a_2022_12_21') as a(create_time date,id int,name varchar(50));

结果显示:
 

pg 存储过程,PostgreSQL 随笔,数据库,postgresql

其他需要注意的是,我这边都是在一个函数上修改,若是参数都一样的话,他是会在原函数上修改的,所以你们别这样啊,否则都白写了。文章来源地址https://www.toymoban.com/news/detail-774353.html

到了这里,关于进阶数据库系列(十一):PostgreSQL 存储过程的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包赞助服务器费用

相关文章

  • Oracle数据库从入门到精通系列之二十一:Oracle 19c数据库增加重做日志大小

    在此最佳实践中,我们增加了 Oracle 重做日志的大小以提高数据库性能。适当调整数据库重做日志的大小可以减少数据库中的等待事件,从而优化数据库系统。 数据库重做日志至少包含两个文件,负责存储对数据库所做的任何更新。重做日志对于数据库至关重要,因为它们可

    2024年04月26日
    浏览(15)
  • tim实践系列——分布式数据存储与动态数据库扩容

    tim实践系列——分布式数据存储与动态数据库扩容

    前言: tim是去中心化分布式即时通讯引擎。不依赖于任何中心服务器,采用去中心化分布式架构,解决传统中心化通讯方式的问题,去中心化分布式架构的通讯引擎的各个节点之间相互连接,形成一个庞大的分布式网络。可以轻松地扩展服务规模,支持更多的用户和业务需求

    2024年02月02日
    浏览(12)
  • 软考高级系统架构设计师系列论文九十一:论分布式数据库的设计与实现

    软考高级系统架构设计师系列之:分布式存储技术

    2024年02月10日
    浏览(20)
  • Hive数据库系列--Hive文件格式/Hive存储格式/Hive压缩格式

    Hive数据库系列--Hive文件格式/Hive存储格式/Hive压缩格式

    本篇主要讲解一下Hive的文件格式,官方文档见《 https://cwiki.apache.org/confluence/display/Hive/FileFormats》、《 https://cwiki.apache.org/confluence/display/Hive/LanguageManual+DDL#LanguageManualDDL-StorageFormatsStorageFormatsRowFormat,StorageFormat,andSerDe》 HIve的文件存储格式常见的有四种:textfile 、sequencefile、or

    2024年01月22日
    浏览(11)
  • postgresql|数据库|MySQL数据库向postgresql数据库迁移的工具pgloader的部署和初步使用

    postgresql|数据库|MySQL数据库向postgresql数据库迁移的工具pgloader的部署和初步使用

    MySQL数据库和postgresql数据库之间的差异并不多,这里的差异指的是对SQL语言的支持两者并不大,但底层的东西差异是非常多的,例如,MySQL的innodb引擎概念,数据库用户管理,这些和postgresql相比是完全不同的(MySQL用户就是用户,没有角色,postgresql有用户,有角色,但差异不

    2024年02月14日
    浏览(16)
  • postgresql数据库定时备份到远程数据库

    postgresql数据库定时备份到远程数据库

    1.老规矩,服务器目录结构: conf目录无内容 profile: 其中: 最后一行 export PGPASSWORD=‘root’ 是需要备份的数据库的密码,因为直接用 pg_dump 命令备份需要输入密码交互,而我们需要达到自动备份,所以借助这种方式不需要输入密码 docker-compose.yml: 启动容器: 然后再data目录下面

    2024年02月09日
    浏览(12)
  • 【数据库】什么是 PostgreSQL?开源数据库系统

    【数据库】什么是 PostgreSQL?开源数据库系统

    PostgreSQL 是一个开源的对象关系数据库系统,本文,我们将讨论 PostgreSQL、它的用途和好处。 PostgreSQL 是由 PostgreSQL Global Development Group 开发的高级 开源关系数据库管理系统(RDBMS) 。它作为 POSTGRES 项目的一部分于 1986 年在加州大学伯克利分校启动,它最初于 1996 年 7 月 8 日发布

    2023年04月08日
    浏览(13)
  • 数据库第十章(数据库恢复技术)十一章(并发控制)

    数据库第十章(数据库恢复技术)十一章(并发控制)

    目录 1.事务 2.并发控制 1.事务 事务的特点:ACID 原子性   atom 一致性   consistent 隔离性   isolation 持久性   durable 故障的种类 1.事务内部故障         措施:采取redo重做和undo撤销技术 2.系统故障DBMS         措施:重启 3.介质故障         硬件损坏 4.计算机病毒   数据恢

    2024年02月09日
    浏览(11)
  • PostgreSQL Linux操作PostgreSQL数据库

    PostgreSQL教程 菜鸟教程:https://www.runoob.com/postgresql/postgresql-tutorial.html 登录PG数据库:psql -U 用户名(U需要大写) 登录PG数据库(指定主机、端口,并进入指定数据库): psql -U 用户名 -h 127.0.0.1 -p 5432 -d 数据库名 -U 登录的用户名 -h 连接的主机(默认127.0.0.1,可替换成远程主机

    2024年02月11日
    浏览(11)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包