Postgresql 每个唯一值执行一次函数

Postgresql 每个唯一值执行一次函数,postgresql,function,Postgresql,Function,我有两个表,其中包含与日常业务相关的数据: CREATE TABLE main_table ( main_id serial, cola text, colb text, colc text, CONSTRAINT main_table_pkey PRIMARY KEY (main_id) ); CREATE TABLE second_table ( second_id serial, main_id integer, cold text, CONSTRAI

我有两个表,其中包含与日常业务相关的数据:

CREATE TABLE main_table (
  main_id serial,
  cola text,
  colb text,
  colc text,
  CONSTRAINT main_table_pkey PRIMARY KEY (main_id)
);

CREATE TABLE second_table (
  second_id serial,
  main_id integer,
  cold text,
  CONSTRAINT second_table_pkey PRIMARY KEY (second_id),
  CONSTRAINT second_table_fkey FOREIGN KEY (main_id)
    REFERENCES main_table (main_id) MATCH SIMPLE
    ON UPDATE NO ACTION ON DELETE NO ACTION
);
我们需要知道这些表中的某些数据何时更新,以便生成出口并推送到第三方。我创建了第三个表来保存更新信息:

CREATE TYPE field AS ENUM ('cola', 'colb', 'colc', 'cold');
CREATE TABLE table_updates (
  main_id int,
  field field
  updated_on date NOT NULL DEFAULT NOW(),
  CONSTRAINT table_updates_fkey FOREIGN KEY (main_id)
    REFERENCES main_table (main_id) MATCH SIMPLE
    ON UPDATE NO ACTION ON DELETE NO ACTION
);
main_table
update
查询之前有一个更新
table_updates
的触发器,可以满足跟踪四列更新中三列的需要

我可以很容易地将相同类型的触发器添加到
second_table
,但是由于
main_id
不是唯一的,因此可以针对单个
main_id
值执行多次该函数,这是不可取的

如何创建一个函数,当更新第二个表中的几行时,每个主id只执行一次

我如何创建一个函数,当更新第二个表中的几行时,每个main\u id只执行一次

如果您的插入是按主id批量插入的,即,
插入tbl(主id…)值(主id…,(主id…,)主id…
,您可以使用来触发一次
插入
更新

对于两者都可以实现的东西,哪一个最好取决于数据库的使用情况每个受影响的行触发一次触发器。规则修改查询或生成附加查询。因此,如果一条语句中的多行受影响,则发出一条额外命令的规则可能比为每一行调用的触发器更快,并且必须多次重新确定要执行的操作。然而,触发方法在概念上比规则方法简单得多,新手更容易掌握正确的方法

在这种情况下,你可能还想看看正常情况,然后。这使您能够使用异步操作。如果这是你的事情,你决定保持触发方法考虑触发更改通知模块,通过。 我的建议是尽可能在应用程序中(DB之外)执行此操作。请记住,在PostgreSQL
temp
中,表是会话的本地表。因此,您可以让每个加载程序会话执行如下操作

BEGIN
  CREATE TEMP TABLE UNLOGGED etl_inventory;
  COPY foo FROM stdin;
  -- Are they different, if so `NOTIFY`
  -- UPSERT
COMMIT;
然后有一个守护进程,当它接收到
NOTIFY
事件时,会将导出添加到导出队列中。

虽然Evan的说法是正确的,但我认为这个问题可以从一个示例中受益

这是我在问题的示例表中使用的规则定义:

CREATE OR REPLACE RULE update_update_table
AS ON UPDATE TO second_table
DO ALSO (
  INSERT INTO table_updates (
    main_id, field
  )
  SELECT DISTINCT OLD.main_id, 'cold'::field
  WHERE NOT EXISTS (
    SELECT TRUE
    FROM table_updates
    WHERE main_id = OLD.main_id
        AND field = 'cold'
  );
  UPDATE table_updates
  SET updated_on = NOW()
  WHERE main_id = OLD.main_id
    AND field = 'cold'
)