场景

余额表历史数据处理,例如202510期间的数据依赖于202509期间的数据,通过循环从启用期间202101开始,依次更新下一个期间的余额。

代码实现

CREATE OR REPLACE FUNCTION compute_balance_amount ( ) returns setof dateList AS $$ 
	DECLARE r dateList % rowtype;
	declare sql_text text;
BEGIN
		FOR r IN SELECT * FROM dateList loop
		
		--上一期的期末余额
		sql_text := 'create or replace view tempBeginAmount
		as 
			select sett_org_id, contact_dept, currency_id, temest_end_period_balance_local, temest_end_period_balance
			from ap_balance_record
			where start_date >= ''' || r.last_start || ''' and end_date <= ''' || r.last_end||'''';
		execute sql_text;
		
		--当前期的合计金额
		sql_text := 'create or replace view tempCurrentAmount
		as 
			select sett_org_id, contact_dept, currency_id, round(sum(arap_amount), 2) arap_amount_sum, round(sum(arap_amount_local), 2) arap_amount_local_sum
			from ap_detail_record
			where biz_date >= '''||r.curr_start||''' and biz_date <= '''||r.curr_end||'''
				and document_type in (''pay'', ''red_pay'', ''other_payable'', ''other_payable_red'', ''ap_er'')
				and sett_org_id = 1
				and biz_type = ''tem_est''
			group by sett_org_id, contact_dept, currency_id';
		execute sql_text;
		
		-- 将待更新的值存入视图
		sql_text := 'CREATE OR REPLACE VIEW tempAllAmount AS
			SELECT
				balance.sett_org_id as sett_org_id, 
				balance.contact_dept as contact_dept, 
				balance.currency_id as currency_id,
				tempBegin.temest_end_period_balance as temest_begin_period_balance,
				tempBegin.temest_end_period_balance_local as temest_begin_period_balance_local,
				COALESCE(NULLIF(arap_amount_sum, NULl), 0) as temest_current_amount,
				COALESCE(NULLIF(arap_amount_local_sum, NULl), 0) as temest_current_amount_local,
				tempBegin.temest_end_period_balance + COALESCE(NULLIF(arap_amount_sum, NULl), 0) as temest_end_period_balance,
				tempBegin.temest_end_period_balance_local + COALESCE(NULLIF(arap_amount_local_sum, NULl), 0) as temest_end_period_balance_local
			FROM ap_balance_record AS balance
				LEFT JOIN tempcurrentamount AS tempCurrent 
					ON balance.sett_org_id = tempCurrent.sett_org_id 
					AND balance.contact_dept = tempCurrent.contact_dept 
					AND balance.currency_id = tempCurrent.currency_id
				RIGHT JOIN tempBeginAmount AS tempBegin 
					ON balance.sett_org_id = tempBegin.sett_org_id 
					AND balance.contact_dept = tempBegin.contact_dept 
					AND balance.currency_id = tempBegin.currency_id 
			WHERE
				balance.start_date >= '''||r.curr_start||''' AND balance.end_date <= '''||r.curr_end||'''';
			execute sql_text;
		
		--更新余额表
		update ap_balance_record balance
		set temest_begin_period_balance = tempAll.temest_begin_period_balance,
			temest_begin_period_balance_local = tempAll.temest_begin_period_balance_local,
			temest_current_amount = tempAll.temest_current_amount, 
			temest_current_amount_local = tempAll.temest_current_amount_local,
			temest_end_period_balance = tempAll.temest_end_period_balance,
			temest_end_period_balance_local = tempAll.temest_end_period_balance_local
		from tempAllAmount tempAll
		where balance.sett_org_id = tempAll.sett_org_id
			and balance.contact_dept = tempAll.contact_dept
			and balance.currency_id = tempAll.currency_id
			and balance.start_date >= r.curr_start AND balance.end_date <= r.curr_end;
			
	RETURN NEXT r;
END loop;
END;
$$ LANGUAGE plpgsql;

--执行存储过程
SELECT compute_balance_amount ();

其他代码技巧

-- 存储过程获取查询结果
CREATE OR REPLACE FUNCTION func_test ( ) 
returns setof table_name AS $$
BEGIN
	-- 如果存储过程返回 setof sometype,则返回值必须在 return next 或者 return query 中声明,然后有一个不带参数的 retrun 命令,告诉函数执行完毕;setof 就意味着多行;
    return query(select * from table_name limit 10);
	return;
END;
$$ LANGUAGE plpgsql;

-- 删除存储过程
DROP FUNCTION func_test();

-- 执行存储过程
SELECT func_test ();  -- 将所有列用,拼接在一起作为返回结果
select * from func_test ();  -- 表作为返回结果

-- returns table() 自定义返回类型
CREATE OR REPLACE FUNCTION update_acct_sys_id() returns table(result text) AS $$
    DECLARE r acct_sys_id_model_view % rowtype;
    declare sql_text text;
BEGIN
    FOR r IN SELECT * FROM acct_sys_id_model_view loop
		-- 利用动态表名更新数据
        sql_text := 'update ' || r.table_name || ' set acct_sys_id = (
            select id from mdm_accounting_system where is_major_accting_sys = true and state = ''audit'' and delete_state = ''normal'') 
            where acct_sys_id is null';
        execute sql_text;
		-- 返回某个查询的结果
        RETURN query(select concat(r.table_name, '的', r.field_name, '字段值更新成功'));
    END loop;
END;
$$ LANGUAGE plpgsql;
Logo

开源鸿蒙跨平台开发社区汇聚开发者与厂商,共建“一次开发,多端部署”的开源生态,致力于降低跨端开发门槛,推动万物智联创新。

更多推荐