Backend - postgresSQL DB 存储过程(数据库存储过程)

目录

一、存储过程的特性

(一)作用

(二)特点

(三)编码结构的区别

二、定时执行存储过程

三、2种编码结构

 (一)函数结构

1. SQL代码

 2. 举例

(1)例1-循环批量插入数据

① 首先,声明函数

② 调用函数

(2)例2-计算面积

① 首先,声明函数

② 调用函数

(二)存储过程结构

1. SQL代码

 2. 举例

(1)首先声明存储过程

(2)调用存储过程

(3)结果是  

​编辑

(三)注意

四、异常处理

1. 异常写法

2. OTHERS

3. RAISE EXCEPTION

4. SQLERRM

五、raise level format 语句

(一)作用

(二)异常等级

(三)举例

1. 展示正常信息

(1)声明时

(2)调用时

(3)结果是

2. 显示异常

(1)声明时

(2)调用时

(3)结果是

六、查询获取数据库的值

1. 声明时

2. 调用时

七、查询多笔记录

(一)第一种

1. 声明时

2. 调用时

3. 结果是

(二)第二种

1. 声明时

2. 调用时

3. 结果是

七、控制结构

(一)if条件

(二)循环

1. while … loop

(1)代码

(2)例子

① 声明时

② 调用存储过程时

2. for 

(1)声明时

(2)调用存储过程时


一、存储过程的特性

(一)作用

        可以将SQL语句存放在数据库服务器上。

(二)特点

        存储于数据库服务器。

        一次编译后,可多次调用。

        有两种编码结构:函数和存储过程。

(三)编码结构的区别

        函数可以在select、update等SQL语句中被调用,而存储过程不能。

        存储过程无需return返回值,函数必须有return返回值。

        存储过程必须用call调用,函数可用select即可。

二、定时执行存储过程

        针对pgadmin软件,使用pg_cron插件或pg_agent插件。但是pg_cron是安装在Unix上,pg_agent

        目前也没有实现Windows安装。

        所以,现在只能用代码调用存储过程。

三、2种编码结构

 (一)函数结构

1. SQL代码

create [or replace] function 函数名(参数名 参数类型, … ) 
returns 返回值类型 as
    $body$
        declare 
            变量名 变量类型;
            变量名 类型 := 值;
            变量名 类型; 变量名 := 值;
        begin 
            函数体; 
        exception when others then 
            raise exception '(%)', sqlerrm;
        end
    $body$
language plpgsql;

 2. 举例

(1)例1-循环批量插入数据
① 首先,声明函数
create or replace function test001 (
    num int
) returns void as 
$$
begin 
    while num <10
    loop 
        insert into public.rep_updhist(id, lastupdate, tablename, starttimekey, endtimekey) values (num, '2024-03-27 15:33:14.014 +0800', 'test0521', '20240101073054822149', '20240327153311867313');
        num = num +1;
    end loop;
exception 
    when others then 
        raise exception '(%)', sqlerrm;
end
$$ 
language plpgsql;
② 调用函数
select test001(8);
(2)例2-计算面积
① 首先,声明函数
create or replace function test002 (
    w int, h int
) returns int as 
$calculator_area$
declare 
    res int := 0;
begin
    res := w * h;
    return res;
exception 
    when others then 
        raise exception '(%)', sqlerrm;
end
$calculator_area$ 
language plpgsql;
② 调用函数
select test002(4,5);

(二)存储过程结构

1. SQL代码

create [or replace] procedure 存储过程名(参数名 参数类型, … )
language plpgsql as
$body$
    declare 
        变量名 变量类型;
        变量名 类型 := 值;
        变量名 类型; 变量名 := 值;
    begin 
        SQL 语句; 
    exception when others then 
        rollback;
    end
$body$

 2. 举例

(1)首先声明存储过程
create or replace procedure testpro001("w" in integer, "h" in integer, "msg" inout text)
language plpgsql as
$$
declare
    res_area integer := 0;
begin 
    res_area := w * h;
    msg := msg||res_area;
    raise notice '控制台展示面积数据:%', res_area;
end;
$$
(2)调用存储过程
call testpro001(4,6, '面积的计算结果是');
(3)结果是  

(三)注意

1. 每句末尾必须带分号隔开。

2. 字串相加的连接符号是 ||,而不是+。

3. format部分中,%是占位符,接收变量的值。例如, aa变量值是23, bb := '结果是%',aa;  则bb的值是'结果是23'。

4. 在函数中,若returns返回值类型是void,则无需return,否则得写上 return 变量名。

5. 报错

        SQL 错误 [42725]: ERROR: procedure testpro001(integer, integer, integer) is not unique
  Hint: Could not choose a best candidate procedure. You might need to add explicit type casts.
  Position: 6

        解决:查看存储过程文件夹中,是否有重复的方法名(或存储过程名)。

6. 执行函数时,若函数名已经存在,但参数类型有变,则会生成函数名重复的函数。同理,执行过程也是。

7. 保留大小写,需要加上双引号。

        解决:使用“”,或者使用quote_ident('XXX'),给字符串加上双引号

四、异常处理

1. 异常写法

exception when others then 
    rollback;
    raise exception '异常是%', sqlerrm;

2. OTHERS

        表示除了声明外的错误。

3. RAISE EXCEPTION

        抛出异常。

        举例:raise exception '出现了异常,请检查!'; 

4. SQLERRM

        储存当前错误的详细信息。

        举例:raise exception '异常是%', sqlerrm;

五、raise level format 语句

(一)作用

        显示消息或异常。

(二)异常等级

        DEBUG(向服务器日志写信息)、

        LOG(向服务器日志写信息,优先级更高)、

        INFO、NOTICE和WARNING(把信息写到服务器日志以及转发到客户端应用,优先级逐步升高)、

        EXCEPTION抛出一个错误(强制关闭当前事务)

(三)举例

1. 展示正常信息

(1)声明时
create or replace function get_data()
returns void as 
$$
declare strval text;
begin 
    strval := '一个大写字母' || quote_ident('B') || '!';
    raise notice '这是%', strval;
exception when others then
    raise WARNING '出现异常:(%)', sqlerrm;
end;
$$
language plpgsql;
(2)调用时
select get_data();
(3)结果是

2. 显示异常

(1)声明时
create or replace function get_data()
returns void as 
$$
declare
    strval text;
begin 
    raise notice '这是%', xx;
exception when others then
    -- raise EXCEPTION '出现异常:(%)', sqlerrm;
    raise WARNING '出现异常:(%)', sqlerrm;
end;
$$
language plpgsql;
(2)调用时
select get_data();
(3)结果是

六、查询获取数据库的值

1. 声明时

create or replace procedure testpro001()
language plpgsql as
$calculator_area$
declare 
    qry_book text := '';
    qry_author text := '';
begin
    select name into qry_book from public."myApp_book" where bid = 3; -- 第1种
    execute 'select author from public."myApp_book" where bid = 3' into qry_author; -- 第2种
    raise notice '书籍ID为是3的书名是:%,作者是:%', qry_book, qry_author;
end;
$calculator_area$

2. 调用时

call testpro001();

七、查询多笔记录

(一)第一种

        在声明函数时,定义输出的值(指定out参数,使用return next)

1. 声明时

create or replace function get_record(out out_bid int, out out_card character varying)
returns setof record as 
$$
declare 
    r record;
begin 
    for i in 1..5 loop
        select * into r from public."myApp_book" where bid=i;
        out_bid := r.bid;
        out_card := r.card;
        return next;
    end loop;
end
$$
language plpgsql;

2. 调用时

select * from get_record();

3. 结果是

(二)第二种

        在调用时,定义获取的值(使用return query)

1. 声明时

create or replace function get_record()
returns setof record as 
$$
declare 
    r record;
begin 
    for i in 1..5 loop
        return query(select bid, card from public."myApp_book" where bid=i);
    end loop;
end
$$
language plpgsql;

2. 调用时

select * from get_record() as t(id integer, card character varying);

3. 结果是

七、控制结构

(一)if条件

if … then … elseif … then … else … end if;

其中,end if的后面一定要带上分号;elseif的写法是连接在一起的,中间无空格隔开。

例子:

create or replace procedure testpro001("w" in integer, "h" in integer, "msg" inout text)
language plpgsql as
$$
declare
    res_area integer := 0;
begin 
    res_area := w * h;
    msg := msg||res_area;
    if res_area <= 10 then
        raise notice '面积数据:%,小于10', res_area;
    elseif res_area <= 20 then
        raise notice '面积数据:%,小于20', res_area;
    else
        raise notice '面积数据:%,大于20', res_area;
    end if;
end;
$$
call testpro001(3,6, '求w的值');

(二)循环

1. while … loop

(1)代码
while … loop 
    # 函数体;
end loop;
(2)例子
① 声明时
create or replace procedure testpro001("w" in integer, "h" in integer, "msg" inout text)
language plpgsql as
$$
declare
    res_area integer := 0;
begin 
    while w<=h loop
        w = w+1;
    end loop;
    msg := 'w的值是' || w;
end;
$$
② 调用存储过程时
call testpro001(3,6, '求w的值');

2. for 

(1)声明时
create or replace procedure testpro001()
language plpgsql as
$$
declare
    sumval int := 0;
begin 
    for i in 1..6 loop
        sumval := sumval+i;
    end loop;
    raise notice '总和值:%',sumval;
end;
$$
(2)调用存储过程时
call testpro001();

  • 23
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值