在同一事件之前和之后触发?填写子表PostgreSQL

时间:2016-08-25 09:31:50

标签: postgresql inheritance triggers partitioning return-type

场合

我在PostgreSQL 9.5中有一个用于按时间存储对象位置的数据库。

我有一个名为"位置"的主表。列(仅相关):

  • position_id
  • position_timestamp
  • object_id

它在object_id上划分为100个子表,条件为:

CREATE TABLE position_object_id_00
( CHECK object_id%100 = 0 ) 
INHERITS ( position );

等等其他孩子。我用模数关系进行分区以均匀分配对象。 每个孩子都在position_id and object_id(两个不同的索引)上编入索引。

重定向子项插入的触发器是:

 CREATE TRIGGER insert_position_trigger
     BEFORE INSERT ON position
     FOR EACH ROW EXECUTE PROCEDURE insert_position();

程序insert_position()查找正确的子表以插入数据,插入数据然后返回NEW对象:

CREATE OR REPLACE FUNCTION insert_position() RETURNS TRIGGER AS $insert_position$
  DECLARE

  BEGIN
    --Look for child table
    [...]
    --Insert data in right child table
    [...]

    RETURN NEW;
  END;
$insert_position$ LANGUAGE plpgsql;

我有一个摘要表object_last_known_position,其中包含使用触发器更新的相同列:

CREATE TRIGGER update_object_last_known_position 
   AFTER INSERT OR UPDATE ON position 
   FOR EACH ROW
   EXECUTE PROCEDURE update_object_last_known_position();

过程update_object_last_known_position()基本上检查position_timestamp是否更新,然后删除旧条目并创建一个新条目,其中包含在INSERT或UPDATE查询(NEW)上传递的数据。

问题

所以这两个触发器对同一事件做出反应:插入位置,一个位于之前,另一个位于之后 返回insert_position()的新内容允许我在触发器update_object_last_known_position()中使用NEW,这是绝对必要的。但这样做,它还会将数据插入主表位置。所以我的数据现在重复了。

我之前尝试过放置两个触发器,如果​​我这样插入数据,它们都会执行,但如果我删除"则返回新的"从程序insert_position()开始,update_object_last_known_position()未执行。

我遇到了这个问题,我没有找到一种方法来执行这两个触发器,而不会在插入数据时填充主表位置。

所以,如果您有任何想法,我将非常感激:)

感谢您的帮助!

修改

解决方案

感谢答案

我"合并"我的两个触发器:insert_position()现在直接调用update_object_last_known_position。为此,我使用参数将update_object_last_known_position修改为存储过程。该参数是刚刚创建的位置insert_position()的id,因此我能够找到它并检索信息。 (在另一个触发器内调用update_object_last_known_position意味着我们不能再使用NEW) 显然insert_position()的返回类型现在为NULL,一切正常:)

1 个答案:

答案 0 :(得分:0)

如果我理解你正确,你会尝试:

  1. 停止插入,并将插入替换为另一个表(由触发器确定)
  2. 更新摘要表(delete / insert)以指向新行。
  3. 你的问题是1次停止2发生?这是合乎逻辑的,因为您已停止插入,因此您也已停止对插入内容进行任何处理。

    所以要解决这个问题,你有几个选择(选项1和2相似)

    1. update_object_last_known_position()致电insert_position(),只有一个触发器
    2. insert_position()update_object_last_known_position()创建包装器方法,并且只有一个触发器。
    3. update_object_last_known_position()的触发器放在insert_position()可能插入的所有表中。