最近PG数据库的项目上线完成,有一些bug导致的业务数据异常决定用函数/存储过程处理一下,下面是使用过程中主要用到的一些语法,记录下来分享给大家(重点参考语法就行,业务关系被我脱敏改的稀碎哈哈哈~)
CREATE OR REPLACE FUNCTION doFun()
RETURNS integer AS
$$
declare
V_RECORD RECORD;
V_SUCCESS_COUNT int;
V_EFFECT_ROW_COUNT int;
V_CUSTOMER_NO varchar;
V_ERROR_MES1 varchar;
V_ERROR_MES2 varchar;
V_ERROR_MES3 varchar;
begin
V_SUCCESS_COUNT := 0;
for V_RECORD in (select * from emp ) loop
begin
--开始业务逻辑处理 逻辑判断阻断使用异常抛出中断 RAISE EXCEPTION 'XXXXX';
update dept set status = '03',status_date = now(),update_time = now(),update_oper = 'SYSTEM'
where deptno = V_RECORD.deptno ;
GET DIAGNOSTICS V_EFFECT_ROW_COUNT = ROW_COUNT;
raise notice '序号:% - 开始执行',V_RECORD.serialno;
--判断更新行数是否正常
if V_EFFECT_ROW_COUNT = 1 then
select empno into V_CUSTOMER_NO from T_CUSTOMER
where CUSTOMER_NAME = V_RECORD.name and CERTTYPE = V_RECORD.idtype and CERTNO = V_RECORD.idno
and GENDER = V_RECORD.sex and BIRTH_DATE = V_RECORD.birthday limit 1;
if V_CUSTOMER_NO is null then
raise notice '新增客户信息';
--客户信息新增
select nextval('No_seq') into V_CUSTOMER_NO;
insert into customer (CUSTOMER_ID,CUST_NO,CUSTOMER_TYPE,CUSTOMER_NAME,CERTTYPE,CERTNO,GENDER,BIRTH_DATE,
LINKMAN,CONTACT_ADDR,OICQ,OPENID,CONTACT_TELEPHONE,CONTACT_TELEPHONE_SPARE,EMAIL,COMPANY_PROPER,COMPANY_INDUSTRY_TYPE,
COMPANY_ESTAB_DATE,INSERT_OPER,INSERT_TIME,UPDATE_TIME,UPDATE_OPER)
values( nextval('Id_seq') , V_CUSTOMER_NO,
'01',V_RECORD.Name,V_RECORD.idtype,V_RECORD.idno,V_RECORD.sex,V_RECORD.birthDay,
V_RECORD.name,null,null,null,V_RECORD.phonenumber,null,null,null,null,null,'SYSTEM',now(),now(),'SYSTEM');
else
raise notice '更新客户信息';
--客户信息更新
update t_customer set contact_telephone = V_RECORD.phonenumber ,CUSTOMER_TYPE = '01' ,UPDATE_TIME=now()
where cust_no = V_CUSTOMER_NO;
end if;
--校验客户号是否为空
if V_CUSTOMER_NO is null then
RAISE EXCEPTION '客户号获取或生成有误,执行终止';
end if;
raise notice '客户号:%',V_CUSTOMER_NO;
update temp_deal set remark = '执行成功',dealstate ='Y' ,finishtime =now() where serialno =V_RECORD.serialno;
V_SUCCESS_COUNT = V_SUCCESS_COUNT + 1;
else
RAISE EXCEPTION '数据异常,终止处理';
end if;
EXCEPTION
WHEN others THEN
GET STACKED DIAGNOSTICS V_ERROR_MES1 = MESSAGE_TEXT,V_ERROR_MES2 = PG_EXCEPTION_DETAIL,V_ERROR_MES3 = PG_EXCEPTION_HINT;
raise notice '异常信息:% + % + %',V_ERROR_MES1 ,V_ERROR_MES2,V_ERROR_MES3;
begin
update temp_deal set remark = V_ERROR_MES1 ||V_ERROR_MES2||V_ERROR_MES3 , finishtime =now() where serialno =V_RECORD.serialno;
end;
end;
end loop;
return V_SUCCESS_COUNT;
END
$$ LANGUAGE PLPGSQL;
能看到这里的小伙伴特意给你们准备了一些总结,请注意查收~
1、PG只有函数,它自身就可以实现Oracle的存储过程的功能
2、事务:每一个begin/end 块内部维护一个事务,如果执行出现异常,该模块的事务全部回滚。上述Demo中我在loop循环中也开启了一个begin/end作为子事务,用于每次循环的单独提交回滚。Exception中也单独开启了一个begin/end作为新的事务,用来记录错误信息。
3、异常:PG函数异常和其他的类似,采用层层包裹结构,内层抛出外层处理,最外层选择抛出会程序中断。在异常处理中可以采用DIAGNOSTICS 收集异常信息,它保存最近一次执行的情况,更多资料参考:PG函数异常变量