在 PostgreSQL 中每 k 次插入后提交

问题描述 投票:0回答:1

在 PostgreSQL 中(我使用 14 和 16),我试图创建一个函数,将记录插入到具有两列的表中:标识符(整数)和字符串“Some string”。我想编写一个循环来插入 N 条记录,但在每 K 条插入后提交,以便我可以查看另一个会话中发生的情况。我该怎么做呢?到目前为止,我已经尝试了很多选项,都是这个的一些变体:

DROP TABLE IF EXISTS testtable;
CREATE TABLE IF NOT EXISTS testtable
(
    identifier bigint NOT NULL,
    description character varying(128),
    CONSTRAINT testtable_pkey PRIMARY KEY (identifier)
);
CREATE OR REPLACE FUNCTION insert_records(N INT, K INT)
RETURNS VOID AS $$
DECLARE
  i INT;
BEGIN
  FOR i IN 1..N LOOP
    INSERT INTO testtable (identifier, description) VALUES (i, 'some string');

    IF MOD(i, K) = 0 THEN
      COMMIT;
    END IF;
  END LOOP;

  COMMIT;
END $$ LANGUAGE plpgsql;

SELECT insert_records(10, 2);

SELECT * FROM testtable;

但是对于上述代码,以及我尝试过的每个变体,我都会遇到此错误(例如,在 IF 条件内先提交,然后开始,等等。

ERROR:  invalid transaction termination
CONTEXT:  PL/pgSQL function insert_records(integer,integer) line 9 at COMMIT 

我们如何在每次第 K 次插入后提交?这个函数应该以不同的方式编写吗?谢谢。

postgresql plpgsql commit postgresql-14 postgresql-16
1个回答
0
投票

由于 PostgreSQL 函数在周围事务块的上下文中运行,因此不允许在 PL/pgSQL 函数内使用 COMMIT。要获得可比较的结果,您应该使用 SAVEPOINTROLLBACK TO

尝试这个更新的代码。我在此函数中使用 SAVEPOINT 来识别稍后可以回滚到的事务点。最后,它回滚到最后一个保存点,从而提交最后的一些更改,并提交所有 K 插入。通过这种方式,您可以完成每次第 K 次插入后提交的预期行为。

这是代码;

DROP TABLE IF EXISTS testtable;
CREATE TABLE IF NOT EXISTS testtable
(
    identifier bigint NOT NULL,
    description character varying(128),
    CONSTRAINT testtable_pkey PRIMARY KEY (identifier)
);

CREATE OR REPLACE FUNCTION insert_records(N INT, K INT)
RETURNS VOID AS $$
DECLARE
  i INT;
BEGIN
  FOR i IN 1..N LOOP
    INSERT INTO testtable (identifier, description) VALUES (i, 'some string');

    IF MOD(i, K) = 0 THEN
      -- Commit every K inserts
      COMMIT;
      -- Create a new savepoint
      SAVEPOINT savepoint_insert;
    END IF;
  END LOOP;

  -- Rollback to the last savepoint to keep the changes made after the last commit
  ROLLBACK TO SAVEPOINT savepoint_insert;
  -- Commit the remaining changes
  COMMIT;
END $$ LANGUAGE plpgsql;

-- Call the function
SELECT insert_records(10, 2);

-- Check the results
SELECT * FROM testtable;

希望对你有帮助:)

© www.soinside.com 2019 - 2024. All rights reserved.