【问题标题】:sync two tables after insert插入后同步两个表
【发布时间】:2015-12-21 10:09:25
【问题描述】:

我正在使用 postgresql。我有两个架构 mainsec 只包含一个表 datastore 具有相同的结构(这只是一个摘录) 当其中一个表发生插入时,我试图创建一个触发器以保持两个表同步,但未成功。问题在于某种循环或递归引用。

你能创建一些例子来解决这个问题吗?

我正在解决这个问题,稍后我会发布我的解决方案。 您可以将此代码用作创建模式和表的参考

    CREATE SCHEMA main;
    CREATE SCHEMA sec;
    SET search_path = main, pg_catalog;
    CREATE TABLE datastore (
        fullname character varying,
        age integer
    );
    SET search_path = sec, pg_catalog;
    CREATE TABLE datastore (
        fullname character varying,
        age integer
    );

【问题讨论】:

  • 嗯...为什么?为什么不简单地从两个来源插入到同一个表中?还是让一张桌子成为另一张桌子的视图?
  • 否...外部系统通过选择其中一个表来插入数据。我的兴趣是在插入后复制数据。我无法修改当前行为。是的......它显然很烂
  • 这毫无意义。系统插入两个表之一,您希望它们相同吗?为什么它插入单独的?分离的最初原因是什么(可能不再需要)?我强烈建议将其中一张表替换为可更新的视图。
  • 当前系统随机选择两个表之一。但是需要查询表,所以我需要它们具有相同的值。我没有开发遗留系统,我暂时无法更改。
  • 添加触发器也会修改表定义。触发器需要与创建可更新视图相同的权限。您可以而且应该使用简单的可更新视图。它将有效地使两个表成为一个具有第二个名称的表。无需触发器。

标签: postgresql triggers insert synchronization postgresql-9.3


【解决方案1】:
create OR REPLACE function copytosec() RETURNS TRIGGER AS $$
BEGIN
insert into sec.datastore(fullname,age) values (NEW.fullname,NEW.age); 
RETURN NEW; 
END;
$$ LANGUAGE plpgsql;

create trigger copytosectrigger after insert on public.datastore 
for each row 
execute procedure copytosec();`

【讨论】:

    【解决方案2】:

    可更新的视图是最好的解决方案,就像 (Postgres 9.3+) 一样简单:

    drop table sec.datastore;
    create view sec.datastore
    as select * from main.datastore;
    

    但是,如果由于某些莫名其妙的原因无法执行此操作,请使用pg_trigger_depth() 函数(Postgres 9.2+)确保在复制期间不执行触发函数。 main.datastore 上的触发器可能如下所示:

    create or replace function main.datastore_insert_trigger()
    returns trigger language plpgsql as $$
    begin
        insert into sec.datastore
        select new.fullname, new.age;
        return new;
    end $$;
    
    create trigger datastore_insert_trigger
    before insert on main.datastore
    for each row when (pg_trigger_depth() = 0)
    execute procedure main.datastore_insert_trigger();
    

    sec.datastore 上的触发器应该类似地定义。

    【讨论】:

    • 这是我接受的解决方案。我的 PG 服务器是 9.3,所以我可以使用它。但是,如何解决 Postgres 9.2 之前的服务器的问题? pg_trigger_depth() = 0 有替代方案吗?
    • 在早期版本的 postgres 中,通常没有直接的替代方法。可能的解决方案取决于具体情况。但是,在这种简单的情况下,您根本不需要在触发器声明中使用 when condition,只要表具有主键(或其他非部分唯一约束)。
    猜你喜欢
    • 2013-05-06
    • 1970-01-01
    • 1970-01-01
    • 2011-07-05
    • 1970-01-01
    • 1970-01-01
    • 2015-07-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多