我有一个名为new_schema的模式,其中有一个表result.该表有许多具有继承性的子表,命名为result_23result_45等.

我有35亿行,而数据库运行缓慢.一行有一个名为new_date的时间戳字段.这从"2022-01- 01"开始.我想删除之前的所有行:2023-11-01.

从父表中删除需要太长时间.我try 直接在SP中从子表中删除,由postgres个超级用户执行.如果发生什么事,我可以稍后继续工作.

CREATE OR REPLACE FUNCTION new_schema.delete_old_rows()

RETURNS TABLE (child_table text)
LANGUAGE plpgsql
AS $function$
DECLARE
    child_table text;
    sql_query text;
BEGIN
    FOR child_table IN
        SELECT table_name
        FROM information_schema.tables
        WHERE table_schema = 'new_schema'
        AND table_name LIKE 'result_%'
    loop
        sql_query := 'DELETE FROM new_schema.' || child_table || ' WHERE new_date < ''2023-11-01'';';
        EXECUTE consulta_sql;
        RAISE NOTICE 'Data deleted in table: %', child_table;
    END LOOP;
END
$function$;

循环中每个子表的I DELETE,而且似乎有效(尽管对于大表来说需要很长时间).但当我判断SELECT时,2022年的数据仍然存在.

打印查询字符串时,DELETE看起来很完美:

==同步,由Elderman更正==@elder_man 其中new_date&lt;‘2023-11-01’;"

我试图在每个DELETE后申请COMMIT,但这不起作用.

推荐答案

你想要PROCEDURE而不是FUNCTION.在那里您可以发出COMMIT.参见:

可以这样工作:

CREATE OR REPLACE PROCEDURE new_schema.delete_old_rows()  -- !!!
  -- no RETURNS clause  -- !!!
  LANGUAGE plpgsql AS
$func$
DECLARE
   _child text;
   _row_ct int;
BEGIN
   FOR _child IN
      SELECT quote_ident(table_name)  -- !!!
      FROM   information_schema.tables
      WHERE  table_schema = 'new_schema'
      AND    table_name LIKE 'result_%'
   LOOP
      EXECUTE 'DELETE FROM new_schema.' || _child || ' WHERE new_date < ''2023-11-01''';      
      GET DIAGNOSTICS _row_ct = ROW_COUNT;
      COMMIT;  -- !!!
      RAISE NOTICE '% rows deleted from table: %', _row_ct, _child;
   END LOOP;
END
$func$;

执行CALL(重要!):

CALL new_schema.delete_old_rows();

另请注意,您的原件可能会受到SQL injection次攻击.标识符必须被视为动态SQL中的用户输入.参见:

And you confused variable names: consulta_sql vs. sql_query. I simplified.
While being at it, I added a row count (practically for free). See:

Database相关问答推荐

KUST查询指定时间跨度内里程表&值的差值,并将其滚动到0

数据库设计:多表与单表

如何设计 SaaS 数据库?

Spring 的 JdbcTemplate 是否在查询超时后关闭连接?

将图像文件存储在 Mongo 数据库中,这是个好主意吗?

将数据库表用作作业(job)队列的最佳方式是什么?

多语言数据库,默认回退

对于 Postgres (Windows),有没有像 TOAD 一样好的东西?

Select * 和 Select [列出每个列] 之间有区别吗

游戏中使用什么样的数据库?

CouchDB、MongoDB 和 Redis 中的哪个数据库适合从 Node.js 开始?

如何使用 django 判断 postgresql 数据库中是否存在某些内容?

MySQL 整数 0 与 NULL

Codeigniter - 使用多个数据库

Django:检测数据库后端

您是否应该将自引用表列设为外键?

用于 sql 表中的状态列的类型

如何判断我的 heroku 数据库的记录?

使用 Sinatra 时与数据库对话的最佳方式是什么?

位图索引有何帮助?