Postgres 函数 return 每个模式删除的行数

Postgres function to return number of rows deleted per schema

我正在尝试将 Postgres 存储过程改编为函数,以便向调用者提供一些反馈。

该过程有条件地删除特定模式中的行,我希望该函数执行相同的操作,而且 return 每个模式删除的行数。

原来的存储过程是:

create or replace procedure clear_tenants()
language plpgsql as $function$
declare
    tenant text;
begin
    for tenant in
        select tenant_schema 
        from public.tenant_schema_mappings
    loop
        execute format($ex$
            delete from %I.parent 
            where expiration_date_time < now()
            $ex$, tenant);
    end loop;
end
$function$;

我目前转换成一个函数是:

CREATE OR REPLACE FUNCTION testfun()
RETURNS TABLE(tsname varchar, amount numeric) AS
$BODY$
declare
    tenant text;
    trow record;
BEGIN
    for tenant in
        select tenant_schema 
        from public.tenant_schema_mappings
    loop
        execute format($ex$
            WITH deleted AS (
                delete from %I.parent 
                where expiration_date_time < now()
                IS TRUE RETURNING *
            )
            tsname := tenant;
            amount := (SELECT * FROM deleted;);
            return next;
            $ex$, tenant);
    end loop;
END
$BODY$ language plpgsql;

这可能在各方面都是错误的。我真的很困惑。

使用 SELECT * FROM testfun() 执行此操作时,出现以下错误:

ERROR:  syntax error at or near "tsname"
LINE 7:    tsname := tenant;
           ^
QUERY:  
            WITH deleted AS (
                delete from anhbawys.parent 
                where expiration_date_time < now()
                IS TRUE RETURNING *
            )
            tsname := tenant;
            amount := (SELECT * FROM deleted;);
            return next;
            
CONTEXT:  PL/pgSQL function testfun() line 9 at EXECUTE
SQL state: 42601

很明显我没有正确分配行的列,但我不确定如何分配。

我发现 this question 看起来很相似,但我的理解有点复杂。

如果答案像您的问题一样简单,那么有一个系统目录。

select schemaname , count(n_tup_del)
from pg_catalog.pg_stat_all_tables psat
group by schemaname 

您可以使用 get diagnostics(noddy 函数来表达我的观点)

create or replace function delfunc()
returns void 
as $$
declare 
 affected_rows int ;
begin 
    delete from atable where a > 998 ;
   GET DIAGNOSTICS affected_rows = ROW_COUNT;
   insert into logtable values(affected_rows);
end $$
language plpgsql

您可以在 DELETE 语句后使用 GET DIAGNOSTICS 来获取删除的行数:

CREATE OR REPLACE FUNCTION testfun()
   RETURNS TABLE(tsname varchar, amount bigint) AS
$BODY$
declare
    tenant text;
BEGIN
    for tenant in
        select tenant_schema 
        from tenant_schema_mappings
    loop
        execute format(
           'delete from %I.parent 
            where expiration_date_time < now()', tenant);

        tsname := tenant;
        GET DIAGNOSTICS amount := ROW_COUNT;

        return next;
    end loop;
END
$BODY$ 
language plpgsql;