【问题标题】:Postgres function to return number of rows deleted per schemaPostgres 函数返回每个模式删除的行数
【发布时间】:2022-01-14 15:56:12
【问题描述】:

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

该过程有条件地删除特定架构中的行,我希望该函数执行相同的操作,但还返回为每个架构删除的行数。

原来的存储过程是:

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 看起来很相似,但我的理解有点复杂。

【问题讨论】:

标签: sql postgresql plpgsql


【解决方案1】:

您可以在 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;

【讨论】:

  • 如果来自另一个事务的同时请求在同一张表上发出DELETE,这会反映在这些统计信息中,还是仅与当前事务正确隔离?
  • 那些不是“统计数据”。这是最后一条语句中删除的实际行数。这与删除行时psql 显示的信息相同。它特定于最后一条语句,仅此而已。如果不能同时运行它就不会真正有用。
  • 那你有效地解决了我的问题。一千个感谢你,我的朋友! :)
【解决方案2】:

如果答案和您的问题一样简单,那么有一个系统目录可以解决这个问题。

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

您可以使用 get diagnostics(点头功能来表达我的观点)

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

【讨论】:

  • 有趣。虽然我不太确定:1) 如何正确插入它2) 如果它总是只提供与我的功能相关的统计信息(我不想要其他同时发生的DELETE 操作将在此处反映)
  • 啊我明白你的意思。不,我的问题是一个摘要,但它特别与“函数中EXECUTE 语句删除的行数”有关。
  • @payne 更新了更合适的建议
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-05-13
  • 1970-01-01
相关资源
最近更新 更多