PostgreSQL表的实现历史

PostgreSQL表的实现历史,sql,database,postgresql,database-partitioning,Sql,Database,Postgresql,Database Partitioning,我想实现PostgreSQL表的更改历史记录。该表的定义方式如下: CREATE TABLE "ps_counters" ( "psid" integer NOT NULL, "counter" bigint[] NOT NULL ); 我希望历史记录表如下所示: CREATE TABLE "ps_counters_history" ( "timestamp" timestamp NOT NULL, "psid" integer NOT NULL, "c

我想实现PostgreSQL表的更改历史记录。该表的定义方式如下:

CREATE TABLE "ps_counters"
(
    "psid" integer NOT NULL,
    "counter" bigint[] NOT NULL
);
我希望历史记录表如下所示:

CREATE TABLE "ps_counters_history"
(
    "timestamp" timestamp NOT NULL,
    "psid" integer NOT NULL,
    "counter" bigint[] NOT NULL
);

我需要一个触发器和一个存储过程,它在
ps\u计数器
中的每次更改(插入或更新)时插入
ps\u计数器历史记录
,但是除了防止
ps\u counters\u history
变得太大之外,我还希望每个月对
ps\u counters\u history
表进行分区。

我设法实现了它

CREATE TABLE "ps_counters_history"
(
  "id" serial PRIMARY KEY,
  "timestamp" timestamp NOT NULL DEFAULT clock_timestamp(),
  "psid" integer NOT NULL,
  "counter" bigint[] NOT NULL
);

CREATE OR REPLACE FUNCTION ps_counters_history_trigger()
  RETURNS trigger AS
$BODY$
  DECLARE
    table_name text;
  BEGIN
    table_name := 'ps_counters_history_' || to_char(CURRENT_DATE, 'yyyy_mm');
    IF NOT EXISTS (SELECT 1 FROM pg_class WHERE relname = table_name)
    THEN
      EXECUTE 'CREATE TABLE IF NOT EXISTS ' || table_name ||
              ' () INHERITS (ps_counters_history);';
    END IF;
    EXECUTE 'INSERT INTO ' || table_name ||
            '(psid, counter) VALUES ($1.psid, $1.counter);' USING NEW;
    RETURN NEW;
  END
$BODY$
  LANGUAGE plpgsql;

CREATE TRIGGER ps_counters_history_trigger
AFTER INSERT OR UPDATE ON ps_counters FOR EACH ROW
EXECUTE PROCEDURE ps_counters_history_trigger();

太大了?每个月有多少ps_计数器更改?好的,您已经详细描述了解决方案。你被卡在哪一部分?还有几点建议:1)通常表应该有一个主键2)
now()
返回事务开始的时间,
clock_timestamp()
返回实际时间3)
execute
可以与参数一起使用:
execute'INSERT-INTO'(psid,counter)值($1.psid,$1.counter);'采用新技术仅供参考,如果两个并发事务试图同时运行create if not exists,则create if not exists逻辑将中断。尽管进行了“如果不存在”检查,您仍会得到一个表已存在错误。@Craig Ringer如果我在if中使用
创建表如果不存在
而不是
创建表
,它会防止错误吗?您建议如何解决此问题?@bobeff您好,您找到解决方案了吗?在上面的问题中,我认为最好先创建历史记录表,例如在数据库连接初始化中,这样在触发器中只插入行而不创建表(如果不存在,则解决使用create TABLE/create TABLE时的并发问题)。