原创

PostgreSQL-分页批量复制表-for循环

另有 大表分页提交update见《PostgreSQL-慢sql查询优化过程-大SQL文件分割-大表分页提交update结果》

DO $$
DECLARE
  i integer;
  page_size integer = 1000;
  total_count integer;
  total_page integer;
  total_count_bak bigint;

BEGIN

  SELECT COUNT(*) INTO total_count FROM bos_data_flag_info;
  total_page = total_count / page_size;
  IF total_count % 10 > 0 THEN
    total_page = total_page + 1;
  END IF;
  RAISE NOTICE '共有 % 页,每页 % 条,共有 % 条,', total_page, page_size ,total_count;
  FOR pageNum IN 1..total_page LOOP
   RAISE NOTICE '执行第: % 页', pageNum;

  INSERT INTO bos_data_flag_info_bak SELECT * FROM bos_data_flag_info i 
  --   WHERE NOT EXISTS ( -- 有问题,会导致漏数据
  --   SELECT 1 FROM bos_data_flag_info_bak b WHERE b.id = i.id ) 
  ORDER BY ID ASC LIMIT page_size OFFSET (pageNum - 1) * (page_size) ;

   -- COMMIT非常关键,不然整个for循环就是1个大事务
   -- COMMIT非常关键,不然整个for循环就是1个大事务
   -- COMMIT非常关键,不然整个for循环就是1个大事务
   COMMIT;
  END LOOP;

  -- 开始校验总数
  SELECT COUNT(*) INTO total_count_bak FROM bos_data_flag_info_bak;
  IF total_count_bak = total_count THEN
    RAISE NOTICE '数据条数一致,新老表均有 % 条', total_count_bak ;
  ELSE
    RAISE NOTICE '数据条数不一致';
  END IF;
END;
$$ LANGUAGE plpgsql;

以下来自AI:
PostgreSQL 通过其内置的过程语言 PL/pgSQL 支持 FOR 循环。PL/pgSQL 提供了两种类型的 FOR 循环:一种是基于数值范围的循环,另一种是基于查询结果集的循环。
基于数值范围的循环
这种循环类似于其他编程语言中的 for 循环,它会在一个数值范围内迭代。例如:


    DO $$
    DECLARE
      i integer;
    BEGIN
      FOR i IN 1..10 LOOP
        RAISE NOTICE 'The number is: %', i;
      END LOOP;
    END;
    $$ LANGUAGE plpgsql;
    基于查询结果集的循环
    这种循环会迭代查询结果中的每一行。在每次迭代中,循环变量(通常是一个记录类型)会被设置为结果集中下一行的值。例如:


    DO $$
    DECLARE
      rec record;
    BEGIN
      FOR rec IN SELECT * FROM some_table LOOP
        RAISE NOTICE 'Processing row with id: %', rec.id;
      END LOOP;
    END;
    $$ LANGUAGE plpgsql;
    在这个例子中,some_table 是你要迭代的表的名称。rec 是一个记录类型变量,它在每次循环中都会被设置为 SELECT 语句返回的下一行的值。

    使用 FOR 循环进行数据处理
    FOR 循环可以用于各种数据处理任务,包括但不限于:

    分批处理数据
    动态生成 SQL 语句
    执行重复性的数据库操作
    示例:分批更新数据
    如果你想分批更新一个大表,可以使用 FOR 循环结合 LIMIT 和 OFFSET 来实现:


    DO $$
    DECLARE
      batch_size integer := 1000;
      offset integer := 0;
    BEGIN
      FOR i IN 1..(SELECT CEIL(COUNT(*)::float / batch_size FROM your_table)) LOOP
        UPDATE your_table SET column_to_update = new_value
        WHERE ctid IN (SELECT ctid FROM your_table ORDER BY id LIMIT batch_size OFFSET offset);
        offset := offset + batch_size;
      END LOOP;
    END;
    $$ LANGUAGE plpgsql;
    在这个例子中,your_table 是你要更新的表的名称,column_to_update 是你想要更新的列的名称,new_value 是新的值,ctid 是一个特殊系统列,用于标识行的物理位置,id 是用于排序的列,以确保每次都能选择不同的行。

请注意,虽然 FOR 循环在 PL/pgSQL 中是一个强大的工具,但你应该谨慎使用,特别是对于大规模数据操作,因为不当使用可能会导致性能问题或锁定问题。在处理大量数据时,考虑使用批处理、并行处理或其他优化策略。

正文到此结束
本文目录